def _collate_per_prefix(self) -> List[PrefixSummary]: """ Collate the data per prefix into a list of PrefixSummary objects. Translates the output from _collect into a list of PrefixSummary objects, one per unique prefix found, with the RIR, BGP origins, and IRR routes set. """ all_prefixes = set(self.irrd_per_prefix.keys()).union(set(self.bgp_per_prefix.keys())) summaries_per_prefix = [] for prefix in all_prefixes: rir = self._rir_for_prefix(prefix) bgp_origins = {r.asn for r in self.bgp_per_prefix.get(prefix, []) if r.asn} summary = PrefixSummary(prefix=prefix, rir=rir, bgp_origins=bgp_origins) if prefix in self.irrd_per_prefix: irr_entries = self.irrd_per_prefix[prefix] irr_entries.sort(key=lambda r: r.asn if r.asn else 0) for entry in irr_entries: assert entry.asn is not None, entry assert entry.irr_source, entry if entry.irr_source == "RPKI": target = summary.rpki_routes else: target = summary.irr_routes[entry.irr_source] target.append( PrefixIRRDetail( asn=entry.asn, rpsl_pk=entry.rpsl_pk, rpki_status=entry.rpki_status, rpki_max_length=entry.rpki_max_length, rpsl_text=entry.rpsl_text, ) ) summaries_per_prefix.append(summary) return summaries_per_prefix
def test_report_no_origin(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, rpki_routes=[ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540ML25", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], irr_routes={ "RIPE": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.INFO assert summary.goodness_overall == 2 assert summary.messages == [ ReportMessage( category=MessageCategory.INFO, text="Route objects exist, but prefix not seen in DFZ", ), ReportMessage( category=MessageCategory.INFO, text="RPKI ROA exists, but prefix not seen in DFZ" ), ]
def test_report_no_origin_no_roa(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, irr_routes={ "RADB": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.not_found, rpsl_text="rpsl object text", ) ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.WARNING assert summary.goodness_overall == 1 assert summary.messages == [ ReportMessage( category=MessageCategory.WARNING, text="Expected route object in RIPE, but only found in other IRRs", ), ReportMessage( category=MessageCategory.INFO, text="Route objects exist, but prefix not seen in DFZ" ), ReportMessage( category=MessageCategory.INFO, text="No (covering) RPKI ROA found for route objects" ), ]
def test_report_invalid_origin_other_irr(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, bgp_origins={65540}, irr_routes={ "RIPE": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], "RADB": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65541", asn=65541, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.WARNING assert summary.goodness_overall == 1 assert summary.messages == [ ReportMessage( category=MessageCategory.WARNING, text="Expected route object in RIPE matches BGP origin, but non-matching objects exist in other IRRs", ), ]
def test_report_invalid_origin_expected_irr(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, bgp_origins={65540}, irr_routes={ "RIPE": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65541", asn=65541, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], "RADB": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.DANGER assert summary.goodness_overall == 0 assert summary.messages == [ ReportMessage( category=MessageCategory.DANGER, text="Expected route object in RIPE, but BGP origin does not match. Objects from other IRRs do match BGP origin", ), ]
def test_report_good(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, bgp_origins={65540}, rpki_routes=[ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540ML25", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], irr_routes={ "RIPE": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540ML25", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.SUCCESS assert summary.goodness_overall == 3 assert summary.messages == [ ReportMessage(category=MessageCategory.SUCCESS, text="Everything looks good"), ] assert summary.prefix_sort_key == "42540766411282592856903984951653826560/48"
def test_report_rpki_invalid(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, bgp_origins={65540}, rpki_routes=[ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65541ML25", asn=65541, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ) ], irr_routes={ "RIPE": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.invalid, rpsl_text="rpsl object text", ) ], "RADB": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.invalid, rpsl_text="rpsl object text", ) ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.DANGER assert summary.goodness_overall == 0 assert summary.messages == [ ReportMessage( category=MessageCategory.DANGER, text="RPKI origin does not match BGP origin" ), ReportMessage(category=MessageCategory.DANGER, text="RPKI-invalid route objects found"), ]
def test_report_multiple_irr_origins(): summary = PrefixSummary( prefix=ip_network("2001:db8::/48"), rir=RIR.RIPENCC, bgp_origins={65540}, irr_routes={ "RIPE": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ), ], "RADB": [ PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65540", asn=65540, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ), PrefixIRRDetail( rpsl_pk="2001:db8::/48AS65541", asn=65541, rpki_status=RPKIStatus.valid, rpsl_text="rpsl object text", ), ], }, ) enrich_prefix_summaries_with_report([summary]) assert summary.category_overall == MessageCategory.WARNING assert summary.goodness_overall == 1 assert summary.messages == [ ReportMessage( category=MessageCategory.WARNING, text="Multiple route objects exist with different origins", ), ]