use der_parser::num_bigint::BigUint; use time::OffsetDateTime; use rpki::data_model::aspa::{AspaEContent, AspaValidateError}; use rpki::data_model::rc::{ AsIdentifierChoice, AsIdOrRange, AsResourceSet, IpResourceSet, RcExtensions, ResourceCertKind, ResourceCertificate, RpkixTbsCertificate, SubjectInfoAccess, }; fn dummy_ee(ip_resources: Option, as_resources: Option) -> 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]), 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_aspa() -> AspaEContent { AspaEContent { version: 1, customer_as_id: 64496, provider_as_ids: vec![64497], } } #[test] fn validate_accepts_when_customer_matches_ee_asid() { let aspa = test_aspa(); let ee = dummy_ee( None, Some(AsResourceSet { asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id(64496)])), rdi: None, }), ); aspa.validate_against_ee_cert(&ee) .expect("customer must match"); } #[test] fn validate_rejects_missing_as_resources() { let aspa = test_aspa(); let ee = dummy_ee(None, None); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::EeAsResourcesMissing)); } #[test] fn validate_rejects_as_resources_inherit_or_ranges() { let aspa = test_aspa(); let ee = dummy_ee( None, Some(AsResourceSet { asnum: Some(AsIdentifierChoice::Inherit), rdi: None, }), ); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::EeAsResourcesInherit)); let ee = dummy_ee( None, Some(AsResourceSet { asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Range { min: 64496, max: 64497, }])), rdi: None, }), ); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::EeAsResourcesRangePresent)); } #[test] fn validate_rejects_customer_mismatch() { let aspa = test_aspa(); let ee = dummy_ee( None, Some(AsResourceSet { asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id(64511)])), rdi: None, }), ); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::CustomerAsIdMismatch { .. })); } #[test] fn validate_rejects_ip_resources_present() { let aspa = test_aspa(); let ee = dummy_ee( Some(IpResourceSet { families: vec![] }), Some(AsResourceSet { asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id(64496)])), rdi: None, }), ); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::EeIpResourcesPresent)); } #[test] fn validate_rejects_rdi_present_or_not_single_id() { let aspa = test_aspa(); let ee = dummy_ee( None, Some(AsResourceSet { asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id(64496)])), rdi: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id(64496)])), }), ); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::EeAsResourcesRdiPresent)); let ee = dummy_ee( None, Some(AsResourceSet { asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![ AsIdOrRange::Id(64496), AsIdOrRange::Id(64497), ])), rdi: None, }), ); let err = aspa.validate_against_ee_cert(&ee).unwrap_err(); assert!(matches!(err, AspaValidateError::EeAsResourcesNotSingleId)); }