def test_get_manifest(archive_changeset: ArchiveChangeset, image_name: ImageName): """Test manifest retrieval.""" manifest = archive_changeset.get_manifest(image_name) if image_name.resolve_digest(): assert manifest.get_config_digest() == image_name.resolve_digest() if image_name.tag: assert ArchiveChangeset.get_repository_tag( image_name) in manifest.get_tags()
async def sign_image( self, signer: Signer, src_image_name: ImageName, dest_image_source: ImageSource, dest_image_name: ImageName, signature_type: SignatureTypes = SignatureTypes.SIGN, **kwargs, ) -> ImageSourceSignImage: LOGGER.debug( "%s: %s ...", "Endorsing" if signature_type == SignatureTypes.ENDORSE else "Signing" if signature_type == SignatureTypes.SIGN else "Resigning", src_image_name.resolve_name(), ) dest_image_name = dest_image_name.clone() if dest_image_name.resolve_digest(): dest_image_name.digest = None LOGGER.warning( "It is not possible to store a signed image to a predetermined digest! Adjusted destination: %s", dest_image_name.resolve_name(), ) # Generate a signed image configuration ... data = await self._sign_image_config(signer, src_image_name, signature_type, **kwargs) LOGGER.debug(" Signature:\n%s", data.signature_value) image_config = data.image_config config_digest = image_config.get_digest() LOGGER.debug(" config digest (signed): %s", config_digest) # Generate a new registry manifest ... manifest = data.verify_image_data.manifest.clone() manifest.set_config_digest(config_digest, len(image_config.get_bytes())) data = ImageSourceSignImage( image_config=data.image_config, manifest_signed=manifest, signature_value=data.signature_value, verify_image_data=data.verify_image_data, ) await dest_image_source.put_image( self, dest_image_name, manifest, image_config, data.verify_image_data.compressed_layer_files, **kwargs, ) dest_image_name.digest = manifest.get_digest() if not self.dry_run: LOGGER.debug("Created new image: %s", dest_image_name.resolve_name()) return data
async def replicate_manifest_lists( docker_registry_secure: DockerRegistrySecure): """Replicates manifests lists to the secure docker registry for testing.""" # pylint: disable=protected-access LOGGER.debug("Replicating manifest lists into %s ...", docker_registry_secure.service_name) async with DockerRegistryClientAsync() as docker_registry_client_async: for image in get_test_data_registryv2(): if "tag_resolves_to_manifest_list" not in image: continue digest = image["digests"][ DockerMediaTypes.DISTRIBUTION_MANIFEST_LIST_V2] image_name = ImageName(image["image"], digest=digest, tag=image["tag"]) LOGGER.debug("- %s", image_name) scope = DockerAuthentication.SCOPE_REPOSITORY_PULL_PATTERN.format( image_name.image) auth_header_src = await docker_registry_client_async._get_request_headers( image_name, scope=scope) if not auth_header_src: LOGGER.warning( "Unable to retrieve authentication headers for: %s", image_name) pdrf_image_name = PDRFImageName( image_name.resolve_image(), digest=image_name.resolve_digest(), endpoint=image_name.resolve_endpoint(), tag=image_name.resolve_tag(), ) try: replicate_manifest_list( pdrf_image_name, docker_registry_secure.endpoint, auth_header_dest=docker_registry_secure.auth_header, auth_header_src=auth_header_src, ssl_context_dest=docker_registry_secure.ssl_context, ) except Exception as exception: # pylint: disable=broad-except LOGGER.warning( "Unable to replicate manifest list '%s': %s", image_name, exception, exc_info=True, )
async def put_image_config(self, image_name: ImageName, image_config: ImageConfig, **kwargs): image_name = image_name.clone() if image_name.resolve_digest(): image_name.digest = None LOGGER.debug( "It is not possible to store an image configuration to a non-deterministic digest!" " Adjusted destination: %s", image_name.resolve_name(), ) image_config_digest = image_config.get_digest() name = f"{image_config_digest.sha256}.json" if not await self._file_exists(name): with open(self.archive, "rb+") as file_out: tar_add_file(file_out, name, image_config.get_bytes())
def test_get_layers(archive_manifest: ArchiveManifest, image_name: ImageName): """Test manifest layer retrieval.""" if (image_name.resolve_digest( ) == "sha256:a51f3f9281a1a3d89dce25fec8acffbe9f59ddb67d98e04245c4c886e32d3782" ): assert archive_manifest.get_layers(image_name) == [ "sha256:137120c8596a15ab42c39c0c5cf83ef864b6b65b5516887c895915e87292bd07", "sha256:755520f73bc74ae73b12f53229e401e8d4c584b74f5704d2d36ba7c45e2657cf", "sha256:13fb089903a5e0e9b00d78ba48496da528ce8d81e08a1042ebeced8c35d714cb", "sha256:f86d68f70ca006025a7f7013f69898f78d1d9272c4d3909e3ec4c7f9958da20e", "sha256:7b4a4edd704242cec1710679a088be8aabff25c3a79f4eecbe8d11d57c53a20b", "sha256:ef4724d42630f3022ef67c3f6749e85a13e81b8efcf98fbd517476499f10e5ab", ] else: assert archive_manifest.get_layers(image_name) == [ "sha256:2c2e149ae9a88ae6bee1583459b2d3e5e317877b795c08781fab36eab4b4329f", "sha256:83419ef1d0ad0520c9fc44da4345637e5c05e34fa564ddf2fb6d6f94a6b2d205", "sha256:c2d494c64683fb7edac60aaffc570c514c1c80c797aafcf25b8a9438690da4df", "sha256:d3b1a8ce509767258045f6cc050dfc8cff27f66f9fa8c61c9dc46733e492e0af", "sha256:0a0084e273d71f3b39100a5c209a3208fafdb90e3dd038cded5e2a54265d23fa", ]
def get_manifest(self, image_name: ImageName) -> "ArchiveManifest": """ Retrieves the archive manifest for a given image name from the archive changeset. Args: image_name: The image name. Returns: The corresponding archive manifest. """ if image_name.digest: for manifest in self.get_manifests(): if manifest.get_config_digest() == image_name.resolve_digest(): return manifest else: tag = ArchiveChangeset.get_repository_tag(image_name) for manifest in self.get_manifests(): tags = manifest.get_tags() if tags and tag in manifest.get_tags(): return manifest raise RuntimeError( f"Unable to locate configuration in archive manifest for: {image_name.resolve_name()}" )
async def test_get_manifest_list( docker_registry_secure: DockerRegistrySecure, image: TypingGetTestData, registry_v2_image_source: RegistryV2ImageSource, **kwargs, ): """Test manifest retrieval.""" if "tag_resolves_to_manifest_list" not in image: pytest.skip( f"Image {image['image']} does not reference a manifest list.") image_name = ImageName( image["image"], digest=image["digests"][ DockerMediaTypes.DISTRIBUTION_MANIFEST_LIST_V2], endpoint=docker_registry_secure.endpoint, tag=image["tag"], ) LOGGER.debug("Retrieving manifest list for: %s ...", image_name) manifest = await registry_v2_image_source.get_manifest( image_name, **kwargs) assert isinstance(manifest, RegistryV2Manifest) assert manifest.get_digest() == image_name.resolve_digest()
def test_get_config_digest(archive_manifest: ArchiveManifest, image_name: ImageName): """Test configuration digest retrieval.""" assert archive_manifest.get_config_digest( image_name) == image_name.resolve_digest()
def test_remove_manifest(archive_changeset: ArchiveChangeset, image_name: ImageName): """Test manifest removal.""" assert len(archive_changeset.get_manifests()) == 2 archive_changeset.remove_manifest(image_name.resolve_digest()) assert len(archive_changeset.get_manifests()) == 1