Esempio n. 1
0
def _rewrite_schema_if_necessary(namespace_name, repo_name, tag_name,
                                 manifest):
    # As per the Docker protocol, if the manifest is not schema version 1 and the manifest's
    # media type is not in the Accept header, we return a schema 1 version of the manifest for
    # the amd64+linux platform, if any, or None if none.
    # See: https://docs.docker.com/registry/spec/manifest-v2-2
    mimetypes = [mimetype for mimetype, _ in request.accept_mimetypes]
    if manifest.media_type in mimetypes:
        return manifest.internal_manifest_bytes, manifest.digest, manifest.media_type

    # Short-circuit check: If the mimetypes is empty or just `application/json`, verify we have
    # a schema 1 manifest and return it.
    if not mimetypes or mimetypes == ["application/json"]:
        if manifest.media_type in DOCKER_SCHEMA1_CONTENT_TYPES:
            return manifest.internal_manifest_bytes, manifest.digest, manifest.media_type

    logger.debug(
        "Manifest `%s` not compatible against %s; checking for conversion",
        manifest.digest,
        request.accept_mimetypes,
    )
    converted = registry_model.convert_manifest(manifest, namespace_name,
                                                repo_name, tag_name, mimetypes,
                                                storage)
    if converted is not None:
        return converted.bytes, converted.digest, converted.media_type

    # For back-compat, we always default to schema 1 if the manifest could not be converted.
    schema1 = registry_model.get_schema1_parsed_manifest(
        manifest, namespace_name, repo_name, tag_name, storage)
    if schema1 is None:
        return None, None, None

    return schema1.bytes, schema1.digest, schema1.media_type
Esempio n. 2
0
def _verify_repo_verb(_, namespace, repo_name, tag_name, verb, checker=None):
    permission = ReadRepositoryPermission(namespace, repo_name)
    repo = model.repository.get_repository(namespace, repo_name)
    repo_is_public = repo is not None and model.repository.is_repository_public(repo)
    if not permission.can() and not repo_is_public:
        logger.debug(
            "No permission to read repository %s/%s for user %s with verb %s",
            namespace,
            repo_name,
            get_authenticated_user(),
            verb,
        )
        abort(403)

    if repo is not None and repo.kind.name != "image":
        logger.debug(
            "Repository %s/%s for user %s is not an image repo",
            namespace,
            repo_name,
            get_authenticated_user(),
        )
        abort(405)

    # Make sure the repo's namespace isn't disabled.
    if not registry_model.is_namespace_enabled(namespace):
        abort(400)

    # Lookup the requested tag.
    repo_ref = registry_model.lookup_repository(namespace, repo_name)
    if repo_ref is None:
        abort(404)

    tag = registry_model.get_repo_tag(repo_ref, tag_name)
    if tag is None:
        logger.debug(
            "Tag %s does not exist in repository %s/%s for user %s",
            tag,
            namespace,
            repo_name,
            get_authenticated_user(),
        )
        abort(404)

    # Get its associated manifest.
    manifest = registry_model.get_manifest_for_tag(tag, backfill_if_necessary=True)
    if manifest is None:
        logger.debug("Could not get manifest on %s/%s:%s::%s", namespace, repo_name, tag.name, verb)
        abort(404)

    # Retrieve the schema1-compatible version of the manifest.
    try:
        schema1_manifest = registry_model.get_schema1_parsed_manifest(
            manifest, namespace, repo_name, tag.name, storage
        )
    except ManifestException:
        logger.exception(
            "Could not get manifest on %s/%s:%s::%s", namespace, repo_name, tag.name, verb
        )
        abort(400)

    if schema1_manifest is None:
        abort(404)

    # If there is a data checker, call it first.
    if checker is not None:
        if not checker(tag, schema1_manifest):
            logger.debug(
                "Check mismatch on %s/%s:%s, verb %s", namespace, repo_name, tag.name, verb
            )
            abort(404)

    # Preload the tag's repository information, so it gets cached.
    assert tag.repository.namespace_name
    assert tag.repository.name

    return tag, manifest, schema1_manifest