Beispiel #1
0
def test_features_for():
    vuln_report_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "vulnerabilityreport.json")
    security_info_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "securityinformation.json")

    with open(vuln_report_filename) as vuln_report_file:
        vuln_report = json.load(vuln_report_file)

    with open(security_info_filename) as security_info_file:
        security_info = json.load(security_info_file)

    expected = security_info["data"]
    expected["Layer"]["Features"].sort(key=lambda d: d["Name"])
    generated = SecurityInformation(
        Layer(
            "sha256:b05ac1eeec8635442fa5d3e55d6ef4ad287b9c66055a552c2fd309c334563b0a",
            "",
            "",
            4,
            features_for(vuln_report),
        )).to_dict()

    # Sort the Features' list so that the following assertion holds even if they are out of order
    # (Ordering of the dicts' key iteration is different from Python 2 to 3)
    expected["Layer"]["Features"].sort(key=lambda d: d["Name"])
    generated["Layer"]["Features"].sort(key=lambda d: d["Name"])

    assert generated == expected
Beispiel #2
0
def test_features_for():
    vuln_report_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "vulnerabilityreport.json"
    )
    security_info_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "securityinformation.json"
    )

    with open(vuln_report_filename) as vuln_report_file:
        vuln_report = json.load(vuln_report_file)

        with open(security_info_filename) as security_info_file:
            security_info = json.load(security_info_file)

        assert (
            SecurityInformation(
                Layer(
                    "sha256:b05ac1eeec8635442fa5d3e55d6ef4ad287b9c66055a552c2fd309c334563b0a",
                    "",
                    "",
                    4,
                    features_for(vuln_report),
                )
            ).to_dict()
            == security_info["data"]
        )
Beispiel #3
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, []))
Beispiel #4
0
def test_enrichments_in_features_for():
    vuln_report_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "vulnerabilityreport_withenrichments.json"
    )
    security_info_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "securityinformation_withenrichments.json"
    )

    with open(vuln_report_filename) as vuln_report_file:
        vuln_report = json.load(vuln_report_file)

    with open(security_info_filename) as security_info_file:
        expected = json.load(security_info_file)

    expected["Layer"]["Features"].sort(key=lambda d: d["Name"])
    generated = SecurityInformation(
        Layer(
            "sha256:4b42c2e36b0bedf017e14dc270f315e627a2a0030f453687a06375fa88694298",
            "",
            "",
            4,
            features_for(vuln_report),
        )
    ).to_dict()

    # Sort the Features' list so that the following assertion holds even if they are out of order
    expected["Layer"]["Features"].sort(key=lambda d: d["Name"])
    generated["Layer"]["Features"].sort(key=lambda d: d["Name"])

    assert generated == expected
Beispiel #5
0
def test_features_for():
    vuln_report_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "vulnerabilityreport.json")
    security_info_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "securityinformation.json")

    with open(vuln_report_filename) as vuln_report_file:
        vuln_report = json.load(vuln_report_file)

        with open(security_info_filename) as security_info_file:
            security_info = json.load(security_info_file)

        features_for_sec_info = SecurityInformation(
            Layer(
                "sha256:b05ac1eeec8635442fa5d3e55d6ef4ad287b9c66055a552c2fd309c334563b0a",
                "",
                "",
                4,
                features_for(vuln_report),
            )).to_dict()

        assert json.dumps(
            canonicalize(features_for_sec_info,
                         preserve_sequence_order=False)) == json.dumps(
                             canonicalize(security_info["data"],
                                          preserve_sequence_order=False))
Beispiel #6
0
    def load_security_information(self,
                                  manifest_or_legacy_image,
                                  include_vulnerabilities=False):
        if not isinstance(manifest_or_legacy_image, ManifestDataType):
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.UNSUPPORTED_FOR_INDEXING)

        status = None
        try:
            status = ManifestSecurityStatus.get(
                manifest=manifest_or_legacy_image._db_id)
        except ManifestSecurityStatus.DoesNotExist:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        if status.index_status == IndexStatus.FAILED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.FAILED_TO_INDEX)

        if status.index_status == IndexStatus.MANIFEST_UNSUPPORTED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.UNSUPPORTED_FOR_INDEXING)

        if status.index_status == IndexStatus.IN_PROGRESS:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        assert status.index_status == IndexStatus.COMPLETED

        try:
            report = self._secscan_api.vulnerability_report(
                manifest_or_legacy_image.digest)
        except APIRequestFailure as arf:
            try:
                status.delete_instance()
            except ReadOnlyModeException:
                pass

            return SecurityInformationLookupResult.for_request_error(str(arf))

        if report is None:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        # TODO(alecmerdler): Provide a way to indicate the current scan is outdated (`report.state != status.indexer_hash`)

        return SecurityInformationLookupResult.for_data(
            SecurityInformation(
                Layer(report["manifest_hash"], "", "", 4,
                      features_for(report))))
Beispiel #7
0
def test_features_for():
    vuln_report_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "vulnerabilityreport.json")
    security_info_filename = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), "securityinformation.json")

    with open(vuln_report_filename) as vuln_report_file:
        vuln_report = json.load(vuln_report_file)

        with open(security_info_filename) as security_info_file:
            security_info = json.load(security_info_file)

        assert (SecurityInformation(Layer(
            features_for(vuln_report))).to_dict() == security_info["data"])
Beispiel #8
0
    def load_security_information(self,
                                  manifest_or_legacy_image,
                                  include_vulnerabilities=False):
        status = registry_model.get_security_status(manifest_or_legacy_image)
        if status is None:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.UNKNOWN_MANIFEST_OR_IMAGE)

        if status == SecurityScanStatus.FAILED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.FAILED_TO_INDEX)

        if status == SecurityScanStatus.UNSUPPORTED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.UNSUPPORTED_FOR_INDEXING)

        if status == SecurityScanStatus.QUEUED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        assert status == SecurityScanStatus.SCANNED

        try:
            if include_vulnerabilities:
                data = self._legacy_secscan_api.get_layer_data(
                    manifest_or_legacy_image, include_vulnerabilities=True)
            else:
                data = self._legacy_secscan_api.get_layer_data(
                    manifest_or_legacy_image, include_features=True)
        except APIRequestFailure as arf:
            return SecurityInformationLookupResult.for_request_error(str(arf))

        if data is None:
            # If no data was found but we reached this point, then it indicates we have incorrect security
            # status for the manifest or legacy image. Mark the manifest or legacy image as unindexed
            # so it automatically gets re-indexed.
            if self.app.config.get("REGISTRY_STATE", "normal") == "normal":
                registry_model.reset_security_status(manifest_or_legacy_image)

            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        return SecurityInformationLookupResult.for_data(
            SecurityInformation.from_dict(data))
Beispiel #9
0
    def load_security_information(self,
                                  manifest_or_legacy_image,
                                  include_vulnerabilities=False):
        status = registry_model.get_security_status(manifest_or_legacy_image)
        if status is None:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.UNKNOWN_MANIFEST_OR_IMAGE)

        if status == SecurityScanStatus.FAILED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.FAILED_TO_INDEX)

        if status == SecurityScanStatus.UNSUPPORTED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.UNSUPPORTED_FOR_INDEXING)

        if status == SecurityScanStatus.QUEUED:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        assert status == SecurityScanStatus.SCANNED

        try:
            if include_vulnerabilities:
                data = self._legacy_secscan_api.get_layer_data(
                    manifest_or_legacy_image, include_vulnerabilities=True)
            else:
                data = self._legacy_secscan_api.get_layer_data(
                    manifest_or_legacy_image, include_features=True)
        except APIRequestFailure as arf:
            return SecurityInformationLookupResult.for_request_error(str(arf))

        if data is None:
            return SecurityInformationLookupResult.with_status(
                ScanLookupStatus.NOT_YET_INDEXED)

        return SecurityInformationLookupResult.for_data(
            SecurityInformation.from_dict(data))