예제 #1
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))
예제 #2
0
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", []))
예제 #3
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")
    manifest = registry_model.get_manifest_for_tag(tag)

    registry_model.populate_legacy_images_for_testing(manifest, storage)

    secscan = V2SecurityScanner(app, instance_keys, storage)
    assert secscan.load_security_information(
        manifest).status == ScanLookupStatus.NOT_YET_INDEXED
예제 #4
0
def test_load_security_information_unknown_manifest(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)

    # Delete the manifest.
    Manifest.get(id=manifest._db_id).delete_instance(recursive=True)

    secscan = V2SecurityScanner(app, instance_keys, storage)
    assert (secscan.load_security_information(manifest).status ==
            ScanLookupStatus.UNSUPPORTED_FOR_INDEXING)
예제 #5
0
def test_load_security_information_failed_to_index(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)

    # Set the index status.
    image = shared.get_legacy_image_for_manifest(manifest._db_id)
    image.security_indexed = False
    image.security_indexed_engine = 3
    image.save()

    secscan = V2SecurityScanner(app, instance_keys, storage)
    assert secscan.load_security_information(
        manifest).status == ScanLookupStatus.FAILED_TO_INDEX
예제 #6
0
def move_tag(repository, tag, image_ids, expect_gc=True):
    namespace = repository.namespace_user.username
    name = repository.name

    repo_ref = RepositoryReference.for_repo_obj(repository)
    builder = DockerSchema1ManifestBuilder(namespace, name, tag)

    # NOTE: Building root to leaf.
    parent_id = None
    for image_id in image_ids:
        config = {
            "id": image_id,
            "config": {
                "Labels": {
                    "foo": "bar",
                    "meh": "grah",
                }
            },
        }

        if parent_id:
            config["parent"] = parent_id

        # Create a storage row for the layer blob.
        _, layer_blob_digest = _populate_blob(repository,
                                              image_id.encode("ascii"))

        builder.insert_layer(layer_blob_digest, json.dumps(config))
        parent_id = image_id

    # Store the manifest.
    manifest = builder.build(docker_v2_signing_key)
    registry_model.create_manifest_and_retarget_tag(repo_ref,
                                                    manifest,
                                                    tag,
                                                    storage,
                                                    raise_on_error=True)

    tag_ref = registry_model.get_repo_tag(repo_ref, tag)
    manifest_ref = registry_model.get_manifest_for_tag(tag_ref)
    registry_model.populate_legacy_images_for_testing(manifest_ref, storage)

    if expect_gc:
        assert gc_now(repository) == expect_gc
예제 #7
0
def test_load_security_information(indexed_v2, indexed_v4, expected_status,
                                   initialized_db):
    secscan_model.configure(app, instance_keys, storage)

    repository_ref = registry_model.lookup_repository("devtable", "simple")
    tag = registry_model.find_matching_tag(repository_ref, ["latest"])
    manifest = registry_model.get_manifest_for_tag(tag)
    assert manifest

    registry_model.populate_legacy_images_for_testing(manifest, storage)

    image = shared.get_legacy_image_for_manifest(manifest._db_id)

    if indexed_v2:
        image.security_indexed = False
        image.security_indexed_engine = 3
        image.save()
    else:
        ManifestLegacyImage.delete().where(
            ManifestLegacyImage.manifest == manifest._db_id).execute()

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

    result = secscan_model.load_security_information(manifest, True)

    assert isinstance(result, SecurityInformationLookupResult)
    assert result.status == expected_status
예제 #8
0
def test_images_shared_cas(default_tag_policy, initialized_db):
    """
    A repository, each two tags, pointing to the same image, which has image storage with the same
    *CAS path*, but *distinct records*.

    Deleting the first tag should delete the first image, and its storage, but not the file in
    storage, as it shares its CAS path.
    """
    with assert_gc_integrity(expect_storage_removed=True):
        repository = create_repository()

        # Create two image storage records with the same content checksum.
        content = b"hello world"
        digest = "sha256:" + hashlib.sha256(content).hexdigest()
        preferred = storage.preferred_locations[0]
        storage.put_content({preferred}, storage.blob_path(digest), content)

        is1 = database.ImageStorage.create(content_checksum=digest)
        is2 = database.ImageStorage.create(content_checksum=digest)

        location = database.ImageStorageLocation.get(name=preferred)

        database.ImageStoragePlacement.create(location=location, storage=is1)
        database.ImageStoragePlacement.create(location=location, storage=is2)

        # Temp link so its available.
        model.blob.store_blob_record_and_temp_link_in_repo(
            repository, digest, location, len(content), 120)

        # Ensure the CAS path exists.
        assert storage.exists({preferred}, storage.blob_path(digest))

        repo_ref = RepositoryReference.for_repo_obj(repository)

        # Store a manifest pointing to that path as `first`.
        builder = DockerSchema1ManifestBuilder(
            repository.namespace_user.username, repository.name, "first")
        builder.insert_layer(
            digest,
            json.dumps({
                "id": "i1",
            }),
        )
        manifest = builder.build(docker_v2_signing_key)
        registry_model.create_manifest_and_retarget_tag(repo_ref,
                                                        manifest,
                                                        "first",
                                                        storage,
                                                        raise_on_error=True)

        tag_ref = registry_model.get_repo_tag(repo_ref, "first")
        manifest_ref = registry_model.get_manifest_for_tag(tag_ref)
        registry_model.populate_legacy_images_for_testing(
            manifest_ref, storage)

        # Store another as `second`.
        builder = DockerSchema1ManifestBuilder(
            repository.namespace_user.username, repository.name, "second")
        builder.insert_layer(
            digest,
            json.dumps({
                "id": "i2",
            }),
        )
        manifest = builder.build(docker_v2_signing_key)
        created, _ = registry_model.create_manifest_and_retarget_tag(
            repo_ref, manifest, "second", storage, raise_on_error=True)

        tag_ref = registry_model.get_repo_tag(repo_ref, "second")
        manifest_ref = registry_model.get_manifest_for_tag(tag_ref)
        registry_model.populate_legacy_images_for_testing(
            manifest_ref, storage)

        # Manually retarget the second manifest's blob to the second row.
        try:
            second_blob = ManifestBlob.get(manifest=created._db_id, blob=is1)
            second_blob.blob = is2
            second_blob.save()
        except ManifestBlob.DoesNotExist:
            second_blob = ManifestBlob.get(manifest=created._db_id, blob=is2)
            second_blob.blob = is1
            second_blob.save()

        # Delete the temp reference.
        _delete_temp_links(repository)

        # Ensure the legacy images exist.
        assert_not_deleted(repository, "i1", "i2")

        # Delete the first tag.
        delete_tag(repository, "first")
        assert_deleted(repository, "i1")
        assert_not_deleted(repository, "i2")

        # Ensure the CAS path still exists.
        assert storage.exists({preferred}, storage.blob_path(digest))
예제 #9
0
def _add_legacy_image(namespace, repo_name, tag_name):
    repo_ref = registry_model.lookup_repository(namespace, repo_name)
    tag_ref = registry_model.get_repo_tag(repo_ref, tag_name)
    manifest_ref = registry_model.get_manifest_for_tag(tag_ref)
    registry_model.populate_legacy_images_for_testing(manifest_ref, storage)