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()
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], }
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 ), }, )
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, []))
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)
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)
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
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)
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)
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)
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
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)
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, }, )
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)
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, }, )
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
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))
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
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", []))
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, ), }, )
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)
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), }, )
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)
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
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, }, )
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
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)
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