rpki/tests/test_roa_validate_ee_resources.rs
2026-02-09 19:35:54 +08:00

188 lines
5.8 KiB
Rust

use der_parser::num_bigint::BigUint;
use time::OffsetDateTime;
use rpki::data_model::rc::{
Afi, AsResourceSet, IpAddressChoice, IpAddressFamily, IpAddressOrRange, IpPrefix,
IpResourceSet, RcExtensions, ResourceCertKind, ResourceCertificate, RpkixTbsCertificate,
SubjectInfoAccess,
};
use rpki::data_model::roa::{
RoaAfi, RoaEContent, RoaIpAddress, RoaIpAddressFamily, RoaValidateError,
};
fn dummy_ee(
ip_resources: Option<IpResourceSet>,
as_resources: Option<AsResourceSet>,
) -> ResourceCertificate {
ResourceCertificate {
raw_der: vec![],
tbs: RpkixTbsCertificate {
version: 2,
serial_number: BigUint::from(1u8),
signature_algorithm: "1.2.840.113549.1.1.11".to_string(),
issuer_dn: "CN=issuer".to_string(),
subject_dn: "CN=subject".to_string(),
validity_not_before: OffsetDateTime::UNIX_EPOCH,
validity_not_after: OffsetDateTime::UNIX_EPOCH,
subject_public_key_info: vec![],
extensions: RcExtensions {
basic_constraints_ca: false,
subject_key_identifier: Some(vec![0x01]),
authority_key_identifier: None,
crl_distribution_points_uris: None,
ca_issuers_uris: None,
subject_info_access: Some(SubjectInfoAccess::Ca(
rpki::data_model::rc::SubjectInfoAccessCa {
access_descriptions: vec![],
},
)),
certificate_policies_oid: None,
ip_resources,
as_resources,
},
},
kind: ResourceCertKind::Ee,
}
}
fn test_roa_single_v4_prefix() -> RoaEContent {
RoaEContent {
version: 0,
as_id: 64496,
ip_addr_blocks: vec![RoaIpAddressFamily {
afi: RoaAfi::Ipv4,
addresses: vec![RoaIpAddress {
prefix: rpki::data_model::roa::IpPrefix {
afi: RoaAfi::Ipv4,
prefix_len: 8,
addr: vec![10, 0, 0, 0],
},
max_length: Some(24),
}],
}],
}
}
#[test]
fn validate_accepts_when_prefix_is_covered() {
let roa = test_roa_single_v4_prefix();
let ee = dummy_ee(
Some(IpResourceSet {
families: vec![IpAddressFamily {
afi: Afi::Ipv4,
choice: IpAddressChoice::AddressesOrRanges(vec![IpAddressOrRange::Prefix(
IpPrefix {
afi: Afi::Ipv4,
prefix_len: 0,
addr: vec![0, 0, 0, 0],
},
)]),
}],
}),
None,
);
roa.validate_against_ee_cert(&ee)
.expect("prefix should be covered by 0/0");
}
#[test]
fn validate_rejects_when_as_resources_present() {
let roa = test_roa_single_v4_prefix();
let ee = dummy_ee(
Some(IpResourceSet { families: vec![] }),
Some(AsResourceSet {
asnum: None,
rdi: None,
}),
);
let err = roa.validate_against_ee_cert(&ee).unwrap_err();
assert!(matches!(err, RoaValidateError::EeAsResourcesPresent));
}
#[test]
fn validate_rejects_when_ip_resources_missing() {
let roa = test_roa_single_v4_prefix();
let ee = dummy_ee(None, None);
let err = roa.validate_against_ee_cert(&ee).unwrap_err();
assert!(matches!(err, RoaValidateError::EeIpResourcesMissing));
}
#[test]
fn validate_rejects_when_ip_resources_inherit() {
let roa = test_roa_single_v4_prefix();
let ee = dummy_ee(
Some(IpResourceSet {
families: vec![IpAddressFamily {
afi: Afi::Ipv4,
choice: IpAddressChoice::Inherit,
}],
}),
None,
);
let err = roa.validate_against_ee_cert(&ee).unwrap_err();
assert!(matches!(err, RoaValidateError::EeIpResourcesInherit));
}
#[test]
fn validate_rejects_when_prefix_not_covered() {
let roa = test_roa_single_v4_prefix();
let ee = dummy_ee(
Some(IpResourceSet {
families: vec![IpAddressFamily {
afi: Afi::Ipv4,
choice: IpAddressChoice::AddressesOrRanges(vec![IpAddressOrRange::Prefix(
IpPrefix {
afi: Afi::Ipv4,
prefix_len: 24,
addr: vec![192, 0, 2, 0],
},
)]),
}],
}),
None,
);
let err = roa.validate_against_ee_cert(&ee).unwrap_err();
assert!(matches!(
err,
RoaValidateError::PrefixNotInEeResources { .. }
));
}
#[test]
fn contains_prefix_handles_non_octet_boundary_prefix_len() {
let roa = RoaEContent {
version: 0,
as_id: 64496,
ip_addr_blocks: vec![RoaIpAddressFamily {
afi: RoaAfi::Ipv4,
addresses: vec![RoaIpAddress {
prefix: rpki::data_model::roa::IpPrefix {
afi: RoaAfi::Ipv4,
prefix_len: 16,
addr: vec![0b1010_0000, 0x12, 0, 0], // 160.18.0.0/16
},
max_length: None,
}],
}],
};
let ee = dummy_ee(
Some(IpResourceSet {
families: vec![IpAddressFamily {
afi: Afi::Ipv4,
choice: IpAddressChoice::AddressesOrRanges(vec![IpAddressOrRange::Prefix(
IpPrefix {
afi: Afi::Ipv4,
prefix_len: 9,
addr: vec![0b1010_0000, 0, 0, 0], // 160.0.0.0/9
},
)]),
}],
}),
None,
);
roa.validate_against_ee_cert(&ee)
.expect("160.18.0.0/16 should be covered by 160.0.0.0/9");
}