20260324 完成和routinator对齐snapshot delta replay correctness一致
This commit is contained in:
@@ -10,8 +10,10 @@ use crate::data_model::roa::{IpPrefix, RoaAfi, RoaDecodeError, RoaObject, RoaVal
|
||||
use crate::data_model::signed_object::SignedObjectVerifyError;
|
||||
use crate::policy::{Policy, SignedObjectFailurePolicy};
|
||||
use crate::report::{RfcRef, Warning};
|
||||
use crate::storage::PackFile;
|
||||
use crate::validation::cert_path::{CertPathError, validate_ee_cert_path_with_prevalidated_issuer};
|
||||
use crate::storage::{PackFile, PackTime, VcirLocalOutput, VcirOutputType};
|
||||
use crate::validation::cert_path::{
|
||||
CertPathError, validate_ee_cert_path_with_predecoded_ee,
|
||||
};
|
||||
use crate::validation::manifest::PublicationPointData;
|
||||
use crate::validation::publication_point::PublicationPointSnapshot;
|
||||
use x509_parser::prelude::FromDer;
|
||||
@@ -67,6 +69,7 @@ pub struct AspaAttestation {
|
||||
pub struct ObjectsOutput {
|
||||
pub vrps: Vec<Vrp>,
|
||||
pub aspas: Vec<AspaAttestation>,
|
||||
pub local_outputs_cache: Vec<VcirLocalOutput>,
|
||||
pub warnings: Vec<Warning>,
|
||||
pub stats: ObjectsStats,
|
||||
pub audit: Vec<ObjectAuditEntry>,
|
||||
@@ -148,6 +151,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
return ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -171,6 +175,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
return ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -188,6 +193,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
return ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -246,6 +252,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
return ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -254,12 +261,14 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
|
||||
let mut vrps: Vec<Vrp> = Vec::new();
|
||||
let mut aspas: Vec<AspaAttestation> = Vec::new();
|
||||
let mut local_outputs_cache: Vec<VcirLocalOutput> = Vec::new();
|
||||
|
||||
for (idx, file) in locked_files.iter().enumerate() {
|
||||
if file.rsync_uri.ends_with(".roa") {
|
||||
let _t = timing.as_ref().map(|t| t.span_phase("objects_roa_total"));
|
||||
match process_roa_with_issuer(
|
||||
file,
|
||||
manifest_rsync_uri,
|
||||
issuer_ca_der,
|
||||
&issuer_ca,
|
||||
&issuer_spki,
|
||||
@@ -271,9 +280,10 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
validation_time,
|
||||
timing,
|
||||
) {
|
||||
Ok(mut out) => {
|
||||
Ok((mut out, local_outputs)) => {
|
||||
stats.roa_ok += 1;
|
||||
vrps.append(&mut out);
|
||||
local_outputs_cache.extend(local_outputs);
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
@@ -346,6 +356,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
return ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -357,6 +368,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
let _t = timing.as_ref().map(|t| t.span_phase("objects_aspa_total"));
|
||||
match process_aspa_with_issuer(
|
||||
file,
|
||||
manifest_rsync_uri,
|
||||
issuer_ca_der,
|
||||
&issuer_ca,
|
||||
&issuer_spki,
|
||||
@@ -368,9 +380,10 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
validation_time,
|
||||
timing,
|
||||
) {
|
||||
Ok(att) => {
|
||||
Ok((att, local_output)) => {
|
||||
stats.aspa_ok += 1;
|
||||
aspas.push(att);
|
||||
local_outputs_cache.push(local_output);
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
@@ -443,6 +456,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
return ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -456,6 +470,7 @@ pub fn process_publication_point_for_issuer<P: PublicationPointData>(
|
||||
ObjectsOutput {
|
||||
vrps,
|
||||
aspas,
|
||||
local_outputs_cache,
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -537,6 +552,7 @@ enum ObjectValidateError {
|
||||
|
||||
fn process_roa_with_issuer(
|
||||
file: &PackFile,
|
||||
manifest_rsync_uri: &str,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca: &ResourceCertificate,
|
||||
issuer_spki: &SubjectPublicKeyInfo<'_>,
|
||||
@@ -547,7 +563,7 @@ fn process_roa_with_issuer(
|
||||
issuer_effective_as: Option<&crate::data_model::rc::AsResourceSet>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
) -> Result<Vec<Vrp>, ObjectValidateError> {
|
||||
) -> Result<(Vec<Vrp>, Vec<VcirLocalOutput>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_roa_decode_and_validate_total"));
|
||||
@@ -566,9 +582,9 @@ fn process_roa_with_issuer(
|
||||
roa.signed_object.verify()?;
|
||||
drop(_verify);
|
||||
|
||||
let ee = &roa.signed_object.signed_data.certificates[0].resource_cert;
|
||||
let ee_der = &roa.signed_object.signed_data.certificates[0].raw_der;
|
||||
let ee_crldp_uris = roa.signed_object.signed_data.certificates[0]
|
||||
.resource_cert
|
||||
let ee_crldp_uris = ee
|
||||
.tbs
|
||||
.extensions
|
||||
.crl_distribution_points_uris
|
||||
@@ -579,7 +595,8 @@ fn process_roa_with_issuer(
|
||||
let _cert_path = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_roa_validate_ee_cert_path_total"));
|
||||
let ee = validate_ee_cert_path_with_prevalidated_issuer(
|
||||
validate_ee_cert_path_with_predecoded_ee(
|
||||
ee,
|
||||
ee_der,
|
||||
issuer_ca,
|
||||
issuer_spki,
|
||||
@@ -602,11 +619,52 @@ fn process_roa_with_issuer(
|
||||
)?;
|
||||
drop(_subset);
|
||||
|
||||
Ok(roa_to_vrps(&roa))
|
||||
let vrps = roa_to_vrps(&roa);
|
||||
let source_object_hash = sha256_hex_from_32(&file.sha256);
|
||||
let source_ee_cert_hash = crate::audit::sha256_hex(ee.raw_der.as_slice());
|
||||
let item_effective_until = PackTime::from_utc_offset_datetime(ee.tbs.validity_not_after);
|
||||
let local_outputs = vrps
|
||||
.iter()
|
||||
.map(|vrp| {
|
||||
let prefix = vrp_prefix_to_string(vrp);
|
||||
let payload_json = serde_json::json!({
|
||||
"asn": vrp.asn,
|
||||
"prefix": prefix,
|
||||
"max_length": vrp.max_length,
|
||||
})
|
||||
.to_string();
|
||||
let rule_hash = crate::audit::sha256_hex(
|
||||
format!(
|
||||
"roa-rule:{}:{}:{}:{}",
|
||||
source_object_hash, vrp.asn, prefix, vrp.max_length
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
VcirLocalOutput {
|
||||
output_id: rule_hash.clone(),
|
||||
output_type: VcirOutputType::Vrp,
|
||||
item_effective_until: item_effective_until.clone(),
|
||||
source_object_uri: file.rsync_uri.clone(),
|
||||
source_object_type: "roa".to_string(),
|
||||
source_object_hash: source_object_hash.clone(),
|
||||
source_ee_cert_hash: source_ee_cert_hash.clone(),
|
||||
payload_json,
|
||||
rule_hash,
|
||||
validation_path_hint: vec![
|
||||
manifest_rsync_uri.to_string(),
|
||||
file.rsync_uri.clone(),
|
||||
source_object_hash.clone(),
|
||||
],
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok((vrps, local_outputs))
|
||||
}
|
||||
|
||||
fn process_aspa_with_issuer(
|
||||
file: &PackFile,
|
||||
manifest_rsync_uri: &str,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca: &ResourceCertificate,
|
||||
issuer_spki: &SubjectPublicKeyInfo<'_>,
|
||||
@@ -617,7 +675,7 @@ fn process_aspa_with_issuer(
|
||||
issuer_effective_as: Option<&crate::data_model::rc::AsResourceSet>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
) -> Result<AspaAttestation, ObjectValidateError> {
|
||||
) -> Result<(AspaAttestation, VcirLocalOutput), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_aspa_decode_and_validate_total"));
|
||||
@@ -636,9 +694,9 @@ fn process_aspa_with_issuer(
|
||||
aspa.signed_object.verify()?;
|
||||
drop(_verify);
|
||||
|
||||
let ee = &aspa.signed_object.signed_data.certificates[0].resource_cert;
|
||||
let ee_der = &aspa.signed_object.signed_data.certificates[0].raw_der;
|
||||
let ee_crldp_uris = aspa.signed_object.signed_data.certificates[0]
|
||||
.resource_cert
|
||||
let ee_crldp_uris = ee
|
||||
.tbs
|
||||
.extensions
|
||||
.crl_distribution_points_uris
|
||||
@@ -649,7 +707,8 @@ fn process_aspa_with_issuer(
|
||||
let _cert_path = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_aspa_validate_ee_cert_path_total"));
|
||||
let ee = validate_ee_cert_path_with_prevalidated_issuer(
|
||||
validate_ee_cert_path_with_predecoded_ee(
|
||||
ee,
|
||||
ee_der,
|
||||
issuer_ca,
|
||||
issuer_spki,
|
||||
@@ -672,10 +731,70 @@ fn process_aspa_with_issuer(
|
||||
)?;
|
||||
drop(_subset);
|
||||
|
||||
Ok(AspaAttestation {
|
||||
let attestation = AspaAttestation {
|
||||
customer_as_id: aspa.aspa.customer_as_id,
|
||||
provider_as_ids: aspa.aspa.provider_as_ids.clone(),
|
||||
})
|
||||
};
|
||||
let source_object_hash = sha256_hex_from_32(&file.sha256);
|
||||
let source_ee_cert_hash = crate::audit::sha256_hex(ee.raw_der.as_slice());
|
||||
let item_effective_until = PackTime::from_utc_offset_datetime(ee.tbs.validity_not_after);
|
||||
let providers = attestation
|
||||
.provider_as_ids
|
||||
.iter()
|
||||
.map(u32::to_string)
|
||||
.collect::<Vec<_>>()
|
||||
.join(",");
|
||||
let rule_hash = crate::audit::sha256_hex(
|
||||
format!(
|
||||
"aspa-rule:{}:{}:{}",
|
||||
source_object_hash, attestation.customer_as_id, providers
|
||||
)
|
||||
.as_bytes(),
|
||||
);
|
||||
let local_output = VcirLocalOutput {
|
||||
output_id: rule_hash.clone(),
|
||||
output_type: VcirOutputType::Aspa,
|
||||
item_effective_until,
|
||||
source_object_uri: file.rsync_uri.clone(),
|
||||
source_object_type: "aspa".to_string(),
|
||||
source_object_hash: source_object_hash.clone(),
|
||||
source_ee_cert_hash,
|
||||
payload_json: serde_json::json!({
|
||||
"customer_as_id": attestation.customer_as_id,
|
||||
"provider_as_ids": attestation.provider_as_ids,
|
||||
})
|
||||
.to_string(),
|
||||
rule_hash,
|
||||
validation_path_hint: vec![
|
||||
manifest_rsync_uri.to_string(),
|
||||
file.rsync_uri.clone(),
|
||||
source_object_hash,
|
||||
],
|
||||
};
|
||||
|
||||
Ok((attestation, local_output))
|
||||
}
|
||||
|
||||
|
||||
fn vrp_prefix_to_string(vrp: &Vrp) -> String {
|
||||
let prefix = &vrp.prefix;
|
||||
match prefix.afi {
|
||||
RoaAfi::Ipv4 => {
|
||||
let addr = std::net::Ipv4Addr::new(
|
||||
prefix.addr[0],
|
||||
prefix.addr[1],
|
||||
prefix.addr[2],
|
||||
prefix.addr[3],
|
||||
);
|
||||
format!("{addr}/{}", prefix.prefix_len)
|
||||
}
|
||||
RoaAfi::Ipv6 => {
|
||||
let mut octets = [0u8; 16];
|
||||
octets.copy_from_slice(&prefix.addr[..16]);
|
||||
let addr = std::net::Ipv6Addr::from(octets);
|
||||
format!("{addr}/{}", prefix.prefix_len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_crl_uri_for_certificate<'a>(
|
||||
|
||||
Reference in New Issue
Block a user