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_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 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 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
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 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", include_legacy_image=True) manifest = registry_model.get_manifest_for_tag(tag, backfill_if_necessary=True, include_legacy_image=True) set_secscan_status(Image.get(id=manifest.legacy_image._db_id), 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 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 manifest_for(namespace, repository, tagname): repository_ref = registry_model.lookup_repository(namespace, repository) tag = registry_model.get_repo_tag(repository_ref, tagname, include_legacy_image=True) return registry_model.get_manifest_for_tag(tag, backfill_if_necessary=True)
def test_get_security_info_with_pull_secret(endpoint, anonymous_allowed, auth_headers, expected_code, client): with patch("features.ANONYMOUS_ACCESS", anonymous_allowed): 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) params = { "repository": "devtable/simple", "imageid": tag.manifest.legacy_image_root_id, "manifestref": manifest.digest, } headers = {} if auth_headers is not None: headers["Authorization"] = auth_headers conduct_api_call(client, endpoint, "GET", params, None, headers=headers, expected_code=expected_code)
def test_deprecated_route(client): 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) with client_with_identity("devtable", client) as cl: resp = conduct_api_call( cl, RepositoryImageSecurity, "get", {"repository": "devtable/simple", "imageid": manifest.legacy_image_root_id}, expected_code=200, ) assert resp.headers["Deprecation"] == "true"
def test_deprecated_route(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) image = shared.get_legacy_image_for_manifest(manifest._db_id) with client_with_identity("devtable", client) as cl: resp = conduct_api_call( cl, RepositoryImageSecurity, "get", {"repository": "devtable/simple", "imageid": image.docker_image_id}, expected_code=200, ) assert resp.headers["Deprecation"] == "true"
def verify_replication_for(namespace, repo_name, tag_name): repo_ref = registry_model.lookup_repository(namespace, repo_name) assert repo_ref tag = registry_model.get_repo_tag(repo_ref, tag_name) assert tag manifest = registry_model.get_manifest_for_tag(tag) assert manifest for layer in registry_model.list_manifest_layers(manifest, storage): if layer.blob.digest != EMPTY_LAYER_BLOB_DIGEST: QueueItem.select().where( QueueItem.queue_name**("%" + layer.blob.uuid + "%")).get() return "OK"
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) if tag_ref is None: raise NotFound() if parsed_args["owned"]: # NOTE: This is deprecated, so we just return empty now. return {"images": []} manifest = registry_model.get_manifest_for_tag(tag_ref) if manifest is None: raise NotFound() legacy_image = registry_model.get_legacy_image( repo_ref, manifest.legacy_image_root_id, storage ) if legacy_image is None: raise NotFound() # NOTE: This is replicating our older response for this endpoint, but # returns empty for the metadata fields. This is to ensure back-compat # for callers still using the deprecated API, while not having to load # all the manifests from storage. return { "images": [ { "id": image_id, "created": format_date(datetime.utcfromtimestamp(tag_ref.lifetime_start_ts)), "comment": "", "command": "", "size": 0, "uploading": False, "sort_index": 0, "ancestors": "", } for image_id in legacy_image.full_image_id_chain ] }