Exemple #1
0
def test_load_security_information_api_request_failure(initialized_db,
                                                       set_secscan_config):
    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.get_repo_tag(repository_ref,
                                      "latest",
                                      include_legacy_image=True)
    manifest = registry_model.get_manifest_for_tag(tag,
                                                   backfill_if_necessary=True)

    mss = ManifestSecurityStatus.create(
        manifest=manifest._db_id,
        repository=repository_ref._db_id,
        error_json={},
        index_status=IndexStatus.COMPLETED,
        indexer_hash="abc",
        indexer_version=IndexerVersion.V4,
        metadata_json={},
    )

    secscan = V4SecurityScanner(app, instance_keys, storage)
    secscan._secscan_api = mock.Mock()
    secscan._secscan_api.vulnerability_report.side_effect = APIRequestFailure()

    assert secscan.load_security_information(
        manifest).status == ScanLookupStatus.COULD_NOT_LOAD
    assert not ManifestSecurityStatus.select().where(
        ManifestSecurityStatus.id == mss.id).exists()
Exemple #2
0
    def get(self, namespace, repository, tag, parsed_args):
        """
        List the images for the specified repository tag.
        """
        repo_ref = registry_model.lookup_repository(namespace, repository)
        if repo_ref is None:
            raise NotFound()

        tag_ref = registry_model.get_repo_tag(repo_ref,
                                              tag,
                                              include_legacy_image=True)
        if tag_ref is None:
            raise NotFound()

        if tag_ref.legacy_image_if_present is None:
            return {"images": []}

        image_id = tag_ref.legacy_image.docker_image_id

        all_images = None
        if parsed_args["owned"]:
            # TODO: Remove the `owned` image concept once we are fully on V2_2.
            all_images = registry_model.get_legacy_images_owned_by_tag(tag_ref)
        else:
            image_with_parents = registry_model.get_legacy_image(
                repo_ref, image_id, include_parents=True)
            if image_with_parents is None:
                raise NotFound()

            all_images = [image_with_parents] + image_with_parents.parents

        return {
            "images": [image_dict(image) for image in all_images],
        }
Exemple #3
0
def monolithic_upload_or_last_chunk(namespace_name, repo_name, upload_uuid):
    # Ensure the digest is present before proceeding.
    digest = request.args.get("digest", None)
    if digest is None:
        raise BlobUploadInvalid(detail={"reason": "Missing digest arg on monolithic upload"})

    # Find the upload.
    repository_ref = registry_model.lookup_repository(namespace_name, repo_name)
    if repository_ref is None:
        raise NameUnknown()

    uploader = retrieve_blob_upload_manager(
        repository_ref, upload_uuid, storage, _upload_settings()
    )
    if uploader is None:
        raise BlobUploadUnknown()

    # Upload the chunk for the blob and commit it once complete.
    with complete_when_uploaded(uploader):
        _upload_chunk(uploader, digest)

    # Write the response to the client.
    return Response(
        status=201,
        headers={
            "Docker-Content-Digest": digest,
            "Location": get_app_url()
            + url_for(
                "v2.download_blob", repository="%s/%s" % (namespace_name, repo_name), digest=digest
            ),
        },
    )
Exemple #4
0
def test_load_security_information_success(initialized_db, set_secscan_config):
    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.get_repo_tag(repository_ref, "latest")
    manifest = registry_model.get_manifest_for_tag(tag)

    ManifestSecurityStatus.create(
        manifest=manifest._db_id,
        repository=repository_ref._db_id,
        error_json={},
        index_status=IndexStatus.COMPLETED,
        indexer_hash="abc",
        indexer_version=IndexerVersion.V4,
        metadata_json={},
    )

    secscan = V4SecurityScanner(app, instance_keys, storage)
    secscan._secscan_api = mock.Mock()
    secscan._secscan_api.vulnerability_report.return_value = {
        "manifest_hash": manifest.digest,
        "state": "IndexFinished",
        "packages": {},
        "distributions": {},
        "repository": {},
        "environments": {},
        "package_vulnerabilities": {},
        "success": True,
        "err": "",
    }

    result = secscan.load_security_information(manifest)

    assert result.status == ScanLookupStatus.SUCCESS
    assert result.security_information == SecurityInformation(
        Layer(manifest.digest, "", "", 4, []))
Exemple #5
0
def update_images(namespace_name, repo_name):
    permission = ModifyRepositoryPermission(namespace_name, repo_name)
    if permission.can():
        logger.debug("Looking up repository")
        repository_ref = registry_model.lookup_repository(namespace_name,
                                                          repo_name,
                                                          kind_filter="image")
        if repository_ref is None:
            # Make sure the repo actually exists.
            image_pushes.labels("v1", 404, "").inc()
            abort(404, message="Unknown repository", issue="unknown-repo")

        builder = lookup_manifest_builder(repository_ref,
                                          session.get("manifest_builder"),
                                          storage, docker_v2_signing_key)
        if builder is None:
            image_pushes.labels("v1", 400, "").inc()
            abort(400)

        # Generate a job for each notification that has been added to this repo
        logger.debug("Adding notifications for repository")
        event_data = {
            "updated_tags": [tag.name for tag in builder.committed_tags],
        }

        builder.done()

        track_and_log("push_repo", repository_ref)
        spawn_notification(repository_ref, "repo_push", event_data)
        image_pushes.labels("v1", 204, "").inc()
        return make_response("Updated", 204)

    image_pushes.labels("v1", 403, "").inc()
    abort(403)
Exemple #6
0
def delete_manifest_by_digest(namespace_name, repo_name, manifest_ref):
    """
    Delete the manifest specified by the digest.

    Note: there is no equivalent method for deleting by tag name because it is
    forbidden by the spec.
    """
    with db_disallow_replica_use():
        repository_ref = registry_model.lookup_repository(
            namespace_name, repo_name)
        if repository_ref is None:
            raise NameUnknown()

        manifest = registry_model.lookup_manifest_by_digest(
            repository_ref, manifest_ref)
        if manifest is None:
            raise ManifestUnknown()

        tags = registry_model.delete_tags_for_manifest(manifest)
        if not tags:
            raise ManifestUnknown()

        for tag in tags:
            track_and_log("delete_tag",
                          repository_ref,
                          tag=tag.name,
                          digest=manifest_ref)

        return Response(status=202)
Exemple #7
0
def test_load_security_information_queued(initialized_db):
    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.get_repo_tag(repository_ref, "latest", include_legacy_image=True)
    manifest = registry_model.get_manifest_for_tag(tag, backfill_if_necessary=True)

    secscan = V4SecurityScanner(app, instance_keys, storage)
    assert secscan.load_security_information(manifest).status == ScanLookupStatus.NOT_YET_INDEXED
Exemple #8
0
def _create_tag(repo, name):
    repo_ref = registry_model.lookup_repository("mirror", "repo")
    with upload_blob(repo_ref, storage, BlobUploadSettings(500, 500,
                                                           500)) as upload:
        app_config = {"TESTING": True}
        config_json = json.dumps({
            "config": {
                "author": u"Repo Mirror",
            },
            "rootfs": {
                "type": "layers",
                "diff_ids": []
            },
            "history": [
                {
                    "created": "2019-07-30T18:37:09.284840891Z",
                    "created_by": "base",
                    "author": u"Repo Mirror",
                },
            ],
        })
        upload.upload_chunk(app_config, BytesIO(config_json))
        blob = upload.commit_to_blob(app_config)
    builder = DockerSchema2ManifestBuilder()
    builder.set_config_digest(blob.digest, blob.compressed_size)
    builder.add_layer("sha256:abcd", 1234, urls=["http://hello/world"])
    manifest = builder.build()

    manifest, tag = registry_model.create_manifest_and_retarget_tag(
        repo_ref, manifest, name, storage)
Exemple #9
0
def get_tag_torrent(namespace_name, repo_name, digest):
    repo = model.repository.get_repository(namespace_name, repo_name)
    repo_is_public = repo is not None and model.repository.is_repository_public(
        repo)

    permission = ReadRepositoryPermission(namespace_name, repo_name)
    if not permission.can() and not repo_is_public:
        abort(403)

    user = get_authenticated_user()
    if user is None and not repo_is_public:
        # We can not generate a private torrent cluster without a user uuid (e.g. token auth)
        abort(403)

    if repo is not None and repo.kind.name != "image":
        abort(405)

    repo_ref = registry_model.lookup_repository(namespace_name, repo_name)
    if repo_ref is None:
        abort(404)

    blob = registry_model.get_repo_blob_by_digest(repo_ref,
                                                  digest,
                                                  include_placements=True)
    if blob is None:
        abort(404)

    return _torrent_for_blob(blob, repo_is_public)
Exemple #10
0
def fetch_manifest_by_tagname(namespace_name, repo_name, manifest_ref, registry_model):
    try:
        repository_ref = registry_model.lookup_repository(
            namespace_name, repo_name, raise_on_error=True, manifest_ref=manifest_ref
        )
    except RepositoryDoesNotExist as e:
        image_pulls.labels("v2", "tag", 404).inc()
        raise NameUnknown("repository not found")

    try:
        tag = registry_model.get_repo_tag(repository_ref, manifest_ref, raise_on_error=True)
    except TagDoesNotExist as e:
        if registry_model.has_expired_tag(repository_ref, manifest_ref):
            logger.debug(
                "Found expired tag %s for repository %s/%s", manifest_ref, namespace_name, repo_name
            )
            msg = (
                "Tag %s was deleted or has expired. To pull, revive via time machine" % manifest_ref
            )
            image_pulls.labels("v2", "tag", 404).inc()
            raise TagExpired(msg)

        image_pulls.labels("v2", "tag", 404).inc()
        raise ManifestUnknown(str(e))

    manifest = registry_model.get_manifest_for_tag(tag)
    if manifest is None:
        # Something went wrong.
        image_pulls.labels("v2", "tag", 400).inc()
        raise ManifestInvalid()

    try:
        manifest_bytes, manifest_digest, manifest_media_type = _rewrite_schema_if_necessary(
            namespace_name, repo_name, manifest_ref, manifest, registry_model
        )
    except (ManifestException, ManifestDoesNotExist) as e:
        image_pulls.labels("v2", "tag", 404).inc()
        raise ManifestUnknown(str(e))

    if manifest_bytes is None:
        image_pulls.labels("v2", "tag", 404).inc()
        raise ManifestUnknown()

    track_and_log(
        "pull_repo",
        repository_ref,
        analytics_name="pull_repo_100x",
        analytics_sample=0.01,
        tag=manifest_ref,
    )
    image_pulls.labels("v2", "tag", 200).inc()

    return Response(
        manifest_bytes.as_unicode(),
        status=200,
        headers={
            "Content-Type": manifest_media_type,
            "Docker-Content-Digest": manifest_digest,
        },
    )
def test_load_security_information(secscan_model):
    repository = registry_model.lookup_repository("devtable", "complex")
    for tag in registry_model.list_all_active_repository_tags(repository):
        manifest = registry_model.get_manifest_for_tag(tag)
        assert manifest
        assert (secscan_model.load_security_information(
            manifest, True).status == ScanLookupStatus.NOT_YET_INDEXED)
Exemple #12
0
def _write_manifest(
    namespace_name, repo_name, tag_name, manifest_impl, registry_model=registry_model
):
    # Ensure that the repository exists.
    repository_ref = registry_model.lookup_repository(namespace_name, repo_name)
    if repository_ref is None:
        raise NameUnknown("repository not found")

    # Create the manifest(s) and retarget the tag to point to it.
    try:
        manifest, tag = registry_model.create_manifest_and_retarget_tag(
            repository_ref, manifest_impl, tag_name, storage, raise_on_error=True
        )
    except CreateManifestException as cme:
        raise ManifestInvalid(detail={"message": str(cme)})
    except RetargetTagException as rte:
        raise ManifestInvalid(detail={"message": str(rte)})

    if manifest is None:
        raise ManifestInvalid()

    if app.config.get("FEATURE_QUOTA_MANAGEMENT", False):
        quota = namespacequota.verify_namespace_quota_force_cache(repository_ref)
        if quota["severity_level"] == "Warning":
            namespacequota.notify_organization_admins(repository_ref, "quota_warning")
        elif quota["severity_level"] == "Reject":
            namespacequota.notify_organization_admins(repository_ref, "quota_error")
            raise QuotaExceeded()

    return repository_ref, manifest, tag
Exemple #13
0
def delete_manifest_by_digest(namespace_name, repo_name, manifest_ref):
    """
    Delete the manifest specified by the digest.

    Note: there is no equivalent method for deleting by tag name because it is
    forbidden by the spec.
    """
    with db_disallow_replica_use():
        repository_ref = registry_model.lookup_repository(namespace_name, repo_name)
        if repository_ref is None:
            raise NameUnknown("repository not found")

        manifest = registry_model.lookup_manifest_by_digest(repository_ref, manifest_ref)
        if manifest is None:
            raise ManifestUnknown()

        tags = registry_model.delete_tags_for_manifest(manifest)
        if not tags:
            raise ManifestUnknown()

        for tag in tags:
            track_and_log("delete_tag", repository_ref, tag=tag.name, digest=manifest_ref)

        if app.config.get("FEATURE_QUOTA_MANAGEMENT", False):
            repository.force_cache_repo_size(repository_ref.id)

        return Response(status=202)
Exemple #14
0
def fetch_manifest_by_digest(namespace_name, repo_name, manifest_ref, registry_model):
    try:
        repository_ref = registry_model.lookup_repository(
            namespace_name, repo_name, raise_on_error=True, manifest_ref=manifest_ref
        )
    except RepositoryDoesNotExist as e:
        image_pulls.labels("v2", "manifest", 404).inc()
        raise NameUnknown("repository not found")

    try:
        manifest = registry_model.lookup_manifest_by_digest(
            repository_ref, manifest_ref, raise_on_error=True
        )
    except ManifestDoesNotExist as e:
        image_pulls.labels("v2", "manifest", 404).inc()
        raise ManifestUnknown(str(e))

    track_and_log("pull_repo", repository_ref, manifest_digest=manifest_ref)
    image_pulls.labels("v2", "manifest", 200).inc()

    return Response(
        manifest.internal_manifest_bytes.as_unicode(),
        status=200,
        headers={
            "Content-Type": manifest.media_type,
            "Docker-Content-Digest": manifest.digest,
        },
    )
Exemple #15
0
def rollback(mirror, since_ms):
    """

  :param mirror: Mirror to perform rollback on
  :param start_time: Time mirror was started; all changes after will be undone
  :return:
  """

    repository_ref = registry_model.lookup_repository(
        mirror.repository.namespace_user.username, mirror.repository.name)
    tags, has_more = registry_model.list_repository_tag_history(
        repository_ref, 1, 100, since_time_ms=since_ms)
    for tag in tags:
        logger.debug("Repo mirroring rollback tag '%s'" % tag)

        # If the tag has an end time, it was either deleted or moved.
        if tag.lifetime_end_ms:
            #  If a future entry exists with a start time equal to the end time for this tag,
            # then the action was a move, rather than a delete and a create.
            newer_tag = filter(
                lambda t: tag != t and tag.name == t.name and tag.
                lifetime_end_ms and t.lifetime_start_ms == tag.lifetime_end_ms,
                tags,
            )[0]
            if newer_tag:
                logger.debug("Repo mirroring rollback revert tag '%s'" % tag)
                retarget_tag(tag.name, tag.manifest._db_id, is_reversion=True)
            else:
                logger.debug("Repo mirroring recreate tag '%s'" % tag)
                retarget_tag(tag.name, tag.manifest._db_id, is_reversion=True)

        #  If the tag has a start time, it was created.
        elif tag.lifetime_start_ms:
            logger.debug("Repo mirroring rollback delete tag '%s'" % tag)
            delete_tag(mirror.repository, tag.name)
Exemple #16
0
def upload_chunk(namespace_name, repo_name, upload_uuid):
    repository_ref = registry_model.lookup_repository(namespace_name, repo_name)
    if repository_ref is None:
        raise NameUnknown("repository not found")

    if app.config.get("FEATURE_QUOTA_MANAGEMENT", False):
        quota = namespacequota.verify_namespace_quota_during_upload(repository_ref)
        if quota["severity_level"] == "Reject":
            namespacequota.notify_organization_admins(
                repository_ref, "quota_error", {"severity": "Reject"}
            )
            raise QuotaExceeded

    uploader = retrieve_blob_upload_manager(
        repository_ref, upload_uuid, storage, _upload_settings()
    )
    if uploader is None:
        raise BlobUploadUnknown()

    # Upload the chunk for the blob.
    _upload_chunk(uploader)

    # Write the response to the client.
    return Response(
        status=202,
        headers={
            "Location": _current_request_url(),
            "Range": _render_range(uploader.blob_upload.byte_count, with_bytes_prefix=False),
            "Docker-Upload-UUID": upload_uuid,
        },
    )
Exemple #17
0
    def delete(self, namespace_name, repository_name, manifestref, labelid):
        """ Deletes an existing label from a manifest. """
        repo_ref = registry_model.lookup_repository(namespace_name,
                                                    repository_name)
        if repo_ref is None:
            raise NotFound()

        manifest = registry_model.lookup_manifest_by_digest(
            repo_ref, manifestref)
        if manifest is None:
            raise NotFound()

        deleted = registry_model.delete_manifest_label(manifest, labelid)
        if deleted is None:
            raise NotFound()

        metadata = {
            'id': labelid,
            'key': deleted.key,
            'value': deleted.value,
            'manifest_digest': manifestref,
            'namespace': namespace_name,
            'repo': repository_name,
        }

        log_action('manifest_label_delete',
                   namespace_name,
                   metadata,
                   repo_name=repository_name)
        return '', 204
Exemple #18
0
    def test_get_layer(self):
        """
        Test for basic retrieval of layers from the security scanner.
        """

        repo_ref = registry_model.lookup_repository(ADMIN_ACCESS_USER,
                                                    SIMPLE_REPO)
        repo_tag = registry_model.get_repo_tag(repo_ref, "latest")
        manifest = registry_model.get_manifest_for_tag(repo_tag)
        registry_model.populate_legacy_images_for_testing(manifest, storage)

        with fake_security_scanner() as security_scanner:
            # Ensure the layer doesn't exist yet.
            self.assertFalse(
                security_scanner.has_layer(
                    security_scanner.layer_id(manifest)))
            self.assertIsNone(self.api.get_layer_data(manifest))

            # Add the layer.
            security_scanner.add_layer(security_scanner.layer_id(manifest))

            # Retrieve the results.
            result = self.api.get_layer_data(manifest,
                                             include_vulnerabilities=True)
            self.assertIsNotNone(result)
            self.assertEquals(result["Layer"]["Name"],
                              security_scanner.layer_id(manifest))
Exemple #19
0
def get_image_json(namespace, repository, image_id, headers):
    logger.debug("Checking repo permissions")
    permission = ReadRepositoryPermission(namespace, repository)
    repository_ref = registry_model.lookup_repository(namespace,
                                                      repository,
                                                      kind_filter="image")
    if not permission.can() and not (repository_ref is not None
                                     and repository_ref.is_public):
        abort(403)

    logger.debug("Looking up repo image")
    legacy_image = registry_model.get_legacy_image(repository_ref,
                                                   image_id,
                                                   store,
                                                   include_blob=True)
    if legacy_image is None:
        flask_abort(404)

    size = legacy_image.blob.compressed_size
    if size is not None:
        # Note: X-Docker-Size is optional and we *can* end up with a NULL image_size,
        # so handle this case rather than failing.
        headers["X-Docker-Size"] = str(size)

    response = make_response(legacy_image.v1_metadata_string, 200)
    response.headers.extend(headers)
    return response
Exemple #20
0
def get_image_ancestry(namespace, repository, image_id, headers):
    logger.debug("Checking repo permissions")
    permission = ReadRepositoryPermission(namespace, repository)
    repository_ref = registry_model.lookup_repository(namespace,
                                                      repository,
                                                      kind_filter="image")
    if not permission.can() and not (repository_ref is not None
                                     and repository_ref.is_public):
        abort(403)

    logger.debug("Looking up repo image")
    legacy_image = registry_model.get_legacy_image(repository_ref,
                                                   image_id,
                                                   include_parents=True)
    if legacy_image is None:
        abort(404,
              "Image %(image_id)s not found",
              issue="unknown-image",
              image_id=image_id)

    # NOTE: We can not use jsonify here because we are returning a list not an object.
    ancestor_ids = [legacy_image.docker_image_id
                    ] + [a.docker_image_id for a in legacy_image.parents]
    response = make_response(json.dumps(ancestor_ids), 200)
    response.headers.extend(headers)
    return response
def test_load_security_information_api_responses(secscan_api_response,
                                                 initialized_db):
    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.get_repo_tag(repository_ref, "latest")
    manifest = registry_model.get_manifest_for_tag(tag)

    registry_model.populate_legacy_images_for_testing(manifest, storage)

    legacy_image_row = shared.get_legacy_image_for_manifest(manifest._db_id)
    assert legacy_image_row is not None
    set_secscan_status(legacy_image_row, True, 3)

    secscan = V2SecurityScanner(app, instance_keys, storage)
    secscan._legacy_secscan_api = mock.Mock()
    secscan._legacy_secscan_api.get_layer_data.return_value = secscan_api_response

    security_information = secscan.load_security_information(
        manifest).security_information

    assert isinstance(security_information, SecurityInformation)
    assert security_information.Layer.Name == secscan_api_response[
        "Layer"].get("Name", "")
    assert security_information.Layer.ParentName == secscan_api_response[
        "Layer"].get("ParentName", "")
    assert security_information.Layer.IndexedByVersion == secscan_api_response[
        "Layer"].get("IndexedByVersion", None)
    assert len(security_information.Layer.Features) == len(
        secscan_api_response["Layer"].get("Features", []))
Exemple #22
0
def write_manifest_by_digest(namespace_name, repo_name, manifest_ref):
    parsed = _parse_manifest()
    if parsed.digest != manifest_ref:
        raise ManifestInvalid(detail={"message": "manifest digest mismatch"})

    if parsed.schema_version != 2:
        return _write_manifest_and_log(namespace_name, repo_name, parsed.tag, parsed)

    # If the manifest is schema version 2, then this cannot be a normal tag-based push, as the
    # manifest does not contain the tag and this call was not given a tag name. Instead, we write the
    # manifest with a temporary tag, as it is being pushed as part of a call for a manifest list.
    repository_ref = registry_model.lookup_repository(namespace_name, repo_name)
    if repository_ref is None:
        raise NameUnknown()

    expiration_sec = app.config["PUSH_TEMP_TAG_EXPIRATION_SEC"]
    manifest = registry_model.create_manifest_with_temp_tag(
        repository_ref, parsed, expiration_sec, storage
    )
    if manifest is None:
        raise ManifestInvalid()

    return Response(
        "OK",
        status=202,
        headers={
            "Docker-Content-Digest": manifest.digest,
            "Location": url_for(
                "v2.fetch_manifest_by_digest",
                repository="%s/%s" % (namespace_name, repo_name),
                manifest_ref=manifest.digest,
            ),
        },
    )
Exemple #23
0
def test_get_security_info_with_pull_secret(endpoint, client):
    repository_ref = registry_model.lookup_repository('devtable', 'simple')
    tag = registry_model.get_repo_tag(repository_ref,
                                      'latest',
                                      include_legacy_image=True)
    manifest = registry_model.get_manifest_for_tag(tag,
                                                   backfill_if_necessary=True)

    params = {
        'repository': 'devtable/simple',
        'imageid': tag.legacy_image.docker_image_id,
        'manifestref': manifest.digest,
    }

    headers = {
        'Authorization': 'Basic %s' % base64.b64encode('devtable:password'),
    }

    conduct_api_call(client,
                     endpoint,
                     'GET',
                     params,
                     None,
                     headers=headers,
                     expected_code=200)
Exemple #24
0
def start_blob_upload(namespace_name, repo_name):
    repository_ref = registry_model.lookup_repository(namespace_name,
                                                      repo_name)
    if repository_ref is None:
        raise NameUnknown()

    # Check for mounting of a blob from another repository.
    mount_blob_digest = request.args.get('mount', None)
    if mount_blob_digest is not None:
        response = _try_to_mount_blob(repository_ref, mount_blob_digest)
        if response is not None:
            return response

    # Begin the blob upload process.
    blob_uploader = create_blob_upload(repository_ref, storage,
                                       _upload_settings())
    if blob_uploader is None:
        logger.debug('Could not create a blob upload for `%s/%s`',
                     namespace_name, repo_name)
        raise InvalidRequest(
            message='Unable to start blob upload for unknown repository')

    # Check if the blob will be uploaded now or in followup calls. If the `digest` is given, then
    # the upload will occur as a monolithic chunk in this call. Otherwise, we return a redirect
    # for the client to upload the chunks as distinct operations.
    digest = request.args.get('digest', None)
    if digest is None:
        # Short-circuit because the user will send the blob data in another request.
        return Response(
            status=202,
            headers={
                'Docker-Upload-UUID':
                blob_uploader.blob_upload_id,
                'Range':
                _render_range(0),
                'Location':
                get_app_url() +
                url_for('v2.upload_chunk',
                        repository='%s/%s' % (namespace_name, repo_name),
                        upload_uuid=blob_uploader.blob_upload_id)
            },
        )

    # Upload the data sent and commit it to a blob.
    with complete_when_uploaded(blob_uploader):
        _upload_chunk(blob_uploader, digest)

    # Write the response to the client.
    return Response(
        status=201,
        headers={
            'Docker-Content-Digest':
            digest,
            'Location':
            get_app_url() + url_for('v2.download_blob',
                                    repository='%s/%s' %
                                    (namespace_name, repo_name),
                                    digest=digest),
        },
    )
Exemple #25
0
def get_repository_images(namespace_name, repo_name):
    repository_ref = registry_model.lookup_repository(namespace_name,
                                                      repo_name,
                                                      kind_filter="image")

    permission = ReadRepositoryPermission(namespace_name, repo_name)
    if permission.can() or (repository_ref and repository_ref.is_public):
        # We can't rely on permissions to tell us if a repo exists anymore
        if repository_ref is None:
            image_pulls.labels("v1", "tag", 404).inc()
            abort(404, message="Unknown repository", issue="unknown-repo")

        logger.debug("Building repository image response")
        resp = make_response(json.dumps([]), 200)
        resp.mimetype = "application/json"

        track_and_log("pull_repo",
                      repository_ref,
                      analytics_name="pull_repo_100x",
                      analytics_sample=0.01)
        image_pulls.labels("v1", "tag", 200).inc()
        return resp

    image_pulls.labels("v1", "tag", 403).inc()
    abort(403)
Exemple #26
0
def test_load_security_information_queued(initialized_db, set_secscan_config):
    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.get_repo_tag(repository_ref, "latest")
    manifest = registry_model.get_manifest_for_tag(tag)

    secscan = V4SecurityScanner(app, instance_keys, storage)
    assert secscan.load_security_information(manifest).status == ScanLookupStatus.NOT_YET_INDEXED
Exemple #27
0
def upload_chunk(namespace_name, repo_name, upload_uuid):
    repository_ref = registry_model.lookup_repository(namespace_name,
                                                      repo_name)
    if repository_ref is None:
        raise NameUnknown()

    uploader = retrieve_blob_upload_manager(repository_ref, upload_uuid,
                                            storage, _upload_settings())
    if uploader is None:
        raise BlobUploadUnknown()

    # Upload the chunk for the blob.
    _upload_chunk(uploader)

    # Write the response to the client.
    return Response(
        status=204,
        headers={
            "Location":
            _current_request_url(),
            "Range":
            _render_range(uploader.blob_upload.byte_count,
                          with_bytes_prefix=False),
            "Docker-Upload-UUID":
            upload_uuid,
        },
    )
Exemple #28
0
    def delete(self, namespace_name, repository_name, manifestref, labelid):
        """
        Deletes an existing label from a manifest.
        """
        repo_ref = registry_model.lookup_repository(namespace_name, repository_name)
        if repo_ref is None:
            raise NotFound()

        manifest = registry_model.lookup_manifest_by_digest(repo_ref, manifestref)
        if manifest is None:
            raise NotFound()

        deleted = registry_model.delete_manifest_label(manifest, labelid)
        if deleted is None:
            raise NotFound()

        metadata = {
            "id": labelid,
            "key": deleted.key,
            "value": deleted.value,
            "manifest_digest": manifestref,
            "namespace": namespace_name,
            "repo": repository_name,
        }

        log_action("manifest_label_delete", namespace_name, metadata, repo_name=repository_name)
        return "", 204
Exemple #29
0
        def wrapped(namespace_name, repo_name, *args, **kwargs):
            logger.debug(
                "Checking permission %s for repo: %s/%s",
                permission_class,
                namespace_name,
                repo_name,
            )

            permission = permission_class(namespace_name, repo_name)
            if permission.can():
                return func(namespace_name, repo_name, *args, **kwargs)

            repository = namespace_name + "/" + repo_name
            if allow_public:
                repository_ref = registry_model.lookup_repository(
                    namespace_name, repo_name)
                if repository_ref is None or not repository_ref.is_public:
                    raise Unauthorized(repository=repository, scopes=scopes)

                if repository_ref.kind != "image":
                    msg = (
                        "This repository is for managing %s and not container images."
                        % repository_ref.kind)
                    raise Unsupported(detail=msg)

                if repository_ref.is_public:
                    if not features.ANONYMOUS_ACCESS:
                        raise Unauthorized(repository=repository,
                                           scopes=scopes)

                    return func(namespace_name, repo_name, *args, **kwargs)

            raise Unauthorized(repository=repository, scopes=scopes)
Exemple #30
0
def test_load_security_information_api_returns_none(initialized_db,
                                                    set_secscan_config):
    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.get_repo_tag(repository_ref,
                                      "latest",
                                      include_legacy_image=True)
    manifest = registry_model.get_manifest_for_tag(tag,
                                                   backfill_if_necessary=True)

    ManifestSecurityStatus.create(
        manifest=manifest._db_id,
        repository=repository_ref._db_id,
        error_json={},
        index_status=IndexStatus.COMPLETED,
        indexer_hash="abc",
        indexer_version=IndexerVersion.V4,
        metadata_json={},
    )

    secscan = V4SecurityScanner(app, instance_keys, storage)
    secscan._secscan_api = mock.Mock()
    secscan._secscan_api.vulnerability_report.return_value = None

    assert secscan.load_security_information(
        manifest).status == ScanLookupStatus.NOT_YET_INDEXED