diff options
| author | J08nY | 2023-04-11 14:53:15 +0200 |
|---|---|---|
| committer | J08nY | 2023-04-11 14:53:15 +0200 |
| commit | 512bc150aecbff5f4e87e37a584dcf2f2a34674f (patch) | |
| tree | 8222357075f014295f7cbf3cb38bca6c2e9bd891 /src/sec_certs | |
| parent | 6d5715b989138da29f90fd8bad46f454903fdd1a (diff) | |
| download | sec-certs-512bc150aecbff5f4e87e37a584dcf2f2a34674f.tar.gz sec-certs-512bc150aecbff5f4e87e37a584dcf2f2a34674f.tar.zst sec-certs-512bc150aecbff5f4e87e37a584dcf2f2a34674f.zip | |
Move snapshot maching code to matcher.
Diffstat (limited to 'src/sec_certs')
| -rw-r--r-- | src/sec_certs/model/fips_matching.py | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/src/sec_certs/model/fips_matching.py b/src/sec_certs/model/fips_matching.py index 0062f8df..2d3fa8a3 100644 --- a/src/sec_certs/model/fips_matching.py +++ b/src/sec_certs/model/fips_matching.py @@ -1,8 +1,18 @@ from __future__ import annotations +import typing +from operator import itemgetter +from typing import Mapping, MutableMapping + from rapidfuzz import fuzz -from sec_certs.sample import FIPSCertificate, IUTEntry, MIPEntry +from sec_certs.configuration import config + +if typing.TYPE_CHECKING: + from sec_certs.dataset.fips import FIPSDataset + from sec_certs.sample.fips import FIPSCertificate + from sec_certs.sample.fips_iut import IUTEntry, IUTSnapshot + from sec_certs.sample.fips_mip import MIPEntry, MIPSnapshot class FIPSProcessMatcher: @@ -28,17 +38,13 @@ class FIPSProcessMatcher: :param cert: The certificate to match against. :return: The match score. """ - # TODO: Add logic to match on date? - # Certification date should be after the entry date in MIP/IUT. - # But a FIPS cert can have many validation dates, gets tricky. - # Maybe this needs to be done outside of the matcher context, - # when comparing several matches. if cert.web_data.standard != self._standard: return 0 if self._product is None or self._vendor is None: return 0 if self._product == cert.name and self._vendor == cert.manufacturer: return 99 + # TODO: Move the CPE matching name/vendor normalization functions and use them here. product_ratings = [ fuzz.token_set_ratio(self._product, cert.name), @@ -49,3 +55,39 @@ class FIPSProcessMatcher: fuzz.partial_token_sort_ratio(self._vendor, cert.manufacturer, score_cutoff=100), ] return max((0, max(product_ratings) * 0.5 + max(vendor_ratings) * 0.5 - 2)) + + @classmethod + def match_snapshot( + cls, snapshot: IUTSnapshot | MIPSnapshot, dset: FIPSDataset + ) -> Mapping[IUTEntry | MIPEntry, FIPSCertificate | None]: + """ + Match a whole snapshot of IUT/MIP entries to a FIPS certificate dataset. + + Duplicates may occur. + + :param snapshot: The snapshot to match the entries of. + :param dset: The dataset tot match to. + :return: The matching. + """ + matches: MutableMapping[IUTEntry | MIPEntry, FIPSCertificate | None] = {} + for entry in snapshot: + matcher = FIPSProcessMatcher(entry) + scores = sorted(((matcher.match(cert), cert) for cert in dset), key=itemgetter(0), reverse=True) + found = False + for score, cert in scores: + if score < config.fips_matching_threshold: + break + validations = cert.web_data.validation_history + if not validations: + continue + for validation in validations: + if validation.date >= snapshot.timestamp.date(): + # It could be this cert, so take it + found = True + matches[entry] = cert + break + if found: + break + else: + matches[entry] = None + return matches |
