20260605 移除audit rule index和DB trace
This commit is contained in:
@@ -14,7 +14,10 @@ use crate::parallel::object_worker::{
|
||||
};
|
||||
use crate::policy::{Policy, SignedObjectFailurePolicy};
|
||||
use crate::report::{RfcRef, Warning};
|
||||
use crate::storage::{PackFile, PackTime, VcirLocalOutput, VcirOutputType};
|
||||
use crate::storage::{
|
||||
PackFile, PackTime, VcirLocalOutput, VcirLocalOutputPayload, VcirOutputType,
|
||||
VcirSourceObjectType,
|
||||
};
|
||||
use crate::validation::cert_path::{CertPathError, validate_signed_object_ee_cert_path_fast};
|
||||
use crate::validation::manifest::PublicationPointData;
|
||||
use crate::validation::publication_point::PublicationPointSnapshot;
|
||||
@@ -28,6 +31,13 @@ const RFC_CRLDP: &[RfcRef] = &[RfcRef("RFC 6487 §4.8.6")];
|
||||
const RFC_CRLDP_AND_LOCKED_PACK: &[RfcRef] =
|
||||
&[RfcRef("RFC 6487 §4.8.6"), RfcRef("RFC 9286 §4.2.1")];
|
||||
|
||||
fn sha256_hex_to_32(hex_value: &str) -> [u8; 32] {
|
||||
let bytes = hex::decode(hex_value).expect("internal sha256 hex should decode");
|
||||
let mut out = [0u8; 32];
|
||||
out.copy_from_slice(&bytes);
|
||||
out
|
||||
}
|
||||
|
||||
fn decode_resource_certificate_with_policy(
|
||||
der: &[u8],
|
||||
policy: &Policy,
|
||||
@@ -132,8 +142,6 @@ pub(crate) struct RoaTaskResult {
|
||||
pub(crate) worker_index: usize,
|
||||
pub(crate) queue_wait_ms: u64,
|
||||
pub(crate) worker_ms: u64,
|
||||
pub(crate) rsync_uri: String,
|
||||
pub(crate) sha256_hex: String,
|
||||
pub(crate) outcome: Result<RoaTaskOk, ObjectValidateError>,
|
||||
}
|
||||
|
||||
@@ -418,8 +426,8 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
local_outputs_cache.extend(ok.local_outputs);
|
||||
}
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: result.rsync_uri,
|
||||
sha256_hex: result.sha256_hex,
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
kind: AuditObjectKind::Roa,
|
||||
result: AuditObjectResult::Ok,
|
||||
detail: None,
|
||||
@@ -428,8 +436,8 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
Err(e) => match policy.signed_object_failure_policy {
|
||||
SignedObjectFailurePolicy::DropObject => {
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: result.rsync_uri.clone(),
|
||||
sha256_hex: result.sha256_hex,
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
kind: AuditObjectKind::Roa,
|
||||
result: AuditObjectResult::Error,
|
||||
detail: Some(e.to_string()),
|
||||
@@ -437,24 +445,21 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
let mut refs = vec![RfcRef("RFC 6488 §3"), RfcRef("RFC 9582 §4-§5")];
|
||||
refs.extend_from_slice(extra_rfc_refs_for_crl_selection(&e));
|
||||
warnings.push(
|
||||
Warning::new(format!(
|
||||
"dropping invalid ROA: {}: {e}",
|
||||
result.rsync_uri
|
||||
))
|
||||
.with_rfc_refs(&refs)
|
||||
.with_context(&result.rsync_uri),
|
||||
Warning::new(format!("dropping invalid ROA: {}: {e}", file.rsync_uri))
|
||||
.with_rfc_refs(&refs)
|
||||
.with_context(&file.rsync_uri),
|
||||
)
|
||||
}
|
||||
SignedObjectFailurePolicy::DropPublicationPoint => {
|
||||
stats.publication_point_dropped = true;
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: result.rsync_uri.clone(),
|
||||
sha256_hex: result.sha256_hex,
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
kind: AuditObjectKind::Roa,
|
||||
result: AuditObjectResult::Error,
|
||||
detail: Some(e.to_string()),
|
||||
});
|
||||
for f in locked_files.iter().skip(result.index + 1) {
|
||||
for f in locked_files.iter().skip(idx + 1) {
|
||||
if f.rsync_uri.ends_with(".roa") {
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: f.rsync_uri.clone(),
|
||||
@@ -484,7 +489,7 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
warnings.push(
|
||||
Warning::new(format!(
|
||||
"dropping publication point due to invalid ROA: {}: {e}",
|
||||
result.rsync_uri
|
||||
file.rsync_uri
|
||||
))
|
||||
.with_rfc_refs(&refs)
|
||||
.with_context(manifest_rsync_uri),
|
||||
@@ -786,19 +791,24 @@ pub fn process_publication_point_for_issuer_parallel_roa_with_pool_options<
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct OwnedRoaTask {
|
||||
pub(crate) publication_point_id: u64,
|
||||
index: usize,
|
||||
file: PackFile,
|
||||
manifest_rsync_uri: String,
|
||||
pub(crate) struct RoaTaskShared {
|
||||
locked_files: Arc<[PackFile]>,
|
||||
manifest_rsync_uri: Arc<str>,
|
||||
issuer_ca_der: Arc<[u8]>,
|
||||
issuer_ca: Arc<ResourceCertificate>,
|
||||
issuer_spki_der: Arc<[u8]>,
|
||||
issuer_ca_rsync_uri: Option<String>,
|
||||
issuer_ca_rsync_uri: Option<Arc<str>>,
|
||||
crl_cache: Arc<Mutex<std::collections::HashMap<String, CachedIssuerCrl>>>,
|
||||
issuer_resources_index: Arc<IssuerResourcesIndex>,
|
||||
issuer_effective_ip: Option<crate::data_model::rc::IpResourceSet>,
|
||||
issuer_effective_as: Option<crate::data_model::rc::AsResourceSet>,
|
||||
issuer_effective_ip: Option<Arc<crate::data_model::rc::IpResourceSet>>,
|
||||
issuer_effective_as: Option<Arc<crate::data_model::rc::AsResourceSet>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct OwnedRoaTask {
|
||||
pub(crate) publication_point_id: u64,
|
||||
index: usize,
|
||||
shared: Arc<RoaTaskShared>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
@@ -862,8 +872,13 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
.map(|submitted_at| worker_started.saturating_duration_since(submitted_at))
|
||||
.map(|duration| duration.as_millis() as u64)
|
||||
.unwrap_or(0);
|
||||
let sha256_hex = sha256_hex_from_32(&task.file.sha256);
|
||||
let issuer_spki = match SubjectPublicKeyInfo::from_der(task.issuer_spki_der.as_ref()) {
|
||||
let shared = task.shared.as_ref();
|
||||
let file = task
|
||||
.shared
|
||||
.locked_files
|
||||
.get(task.index)
|
||||
.expect("ROA task index must reference locked file");
|
||||
let issuer_spki = match SubjectPublicKeyInfo::from_der(shared.issuer_spki_der.as_ref()) {
|
||||
Ok((rem, spki)) if rem.is_empty() => spki,
|
||||
Ok((rem, _)) => {
|
||||
return RoaTaskResult {
|
||||
@@ -872,8 +887,6 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
worker_index,
|
||||
queue_wait_ms,
|
||||
worker_ms: worker_started.elapsed().as_millis() as u64,
|
||||
rsync_uri: task.file.rsync_uri,
|
||||
sha256_hex,
|
||||
outcome: Err(ObjectValidateError::CertPath(
|
||||
CertPathError::IssuerSpkiTrailingBytes(rem.len()),
|
||||
)),
|
||||
@@ -886,8 +899,6 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
worker_index,
|
||||
queue_wait_ms,
|
||||
worker_ms: worker_started.elapsed().as_millis() as u64,
|
||||
rsync_uri: task.file.rsync_uri,
|
||||
sha256_hex,
|
||||
outcome: Err(ObjectValidateError::CertPath(
|
||||
CertPathError::IssuerSpkiParse(e.to_string()),
|
||||
)),
|
||||
@@ -895,16 +906,16 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
}
|
||||
};
|
||||
let outcome = process_roa_with_issuer_parallel_cached(
|
||||
&task.file,
|
||||
task.manifest_rsync_uri.as_str(),
|
||||
task.issuer_ca_der.as_ref(),
|
||||
task.issuer_ca.as_ref(),
|
||||
file,
|
||||
shared.manifest_rsync_uri.as_ref(),
|
||||
shared.issuer_ca_der.as_ref(),
|
||||
shared.issuer_ca.as_ref(),
|
||||
&issuer_spki,
|
||||
task.issuer_ca_rsync_uri.as_deref(),
|
||||
task.crl_cache.as_ref(),
|
||||
task.issuer_resources_index.as_ref(),
|
||||
task.issuer_effective_ip.as_ref(),
|
||||
task.issuer_effective_as.as_ref(),
|
||||
shared.issuer_ca_rsync_uri.as_deref(),
|
||||
shared.crl_cache.as_ref(),
|
||||
shared.issuer_resources_index.as_ref(),
|
||||
shared.issuer_effective_ip.as_deref(),
|
||||
shared.issuer_effective_as.as_deref(),
|
||||
task.validation_time,
|
||||
None,
|
||||
task.collect_vcir_local_outputs,
|
||||
@@ -922,8 +933,6 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
worker_index,
|
||||
queue_wait_ms,
|
||||
worker_ms: worker_started.elapsed().as_millis() as u64,
|
||||
rsync_uri: task.file.rsync_uri,
|
||||
sha256_hex,
|
||||
outcome,
|
||||
}
|
||||
}
|
||||
@@ -935,16 +944,7 @@ pub(crate) enum ParallelObjectsPrepare {
|
||||
|
||||
pub(crate) struct ParallelObjectsStage {
|
||||
pub(crate) publication_point_id: u64,
|
||||
pub(crate) locked_files: Vec<PackFile>,
|
||||
pub(crate) manifest_rsync_uri: String,
|
||||
issuer_ca_der: Arc<[u8]>,
|
||||
issuer_ca: Arc<ResourceCertificate>,
|
||||
issuer_spki_der: Arc<[u8]>,
|
||||
issuer_ca_rsync_uri: Option<String>,
|
||||
crl_cache: Arc<Mutex<std::collections::HashMap<String, CachedIssuerCrl>>>,
|
||||
issuer_resources_index: Arc<IssuerResourcesIndex>,
|
||||
issuer_effective_ip: Option<crate::data_model::rc::IpResourceSet>,
|
||||
issuer_effective_as: Option<crate::data_model::rc::AsResourceSet>,
|
||||
shared: Arc<RoaTaskShared>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
@@ -955,31 +955,41 @@ pub(crate) struct ParallelObjectsStage {
|
||||
}
|
||||
|
||||
impl ParallelObjectsStage {
|
||||
#[cfg(test)]
|
||||
pub(crate) fn build_roa_tasks(&self) -> Vec<OwnedRoaTask> {
|
||||
self.locked_files
|
||||
let mut tasks = Vec::with_capacity(self.roa_task_count());
|
||||
self.extend_roa_tasks(|task| tasks.push(task));
|
||||
tasks
|
||||
}
|
||||
|
||||
pub(crate) fn append_roa_tasks_to(
|
||||
&self,
|
||||
pending: &mut std::collections::VecDeque<OwnedRoaTask>,
|
||||
) {
|
||||
self.extend_roa_tasks(|task| pending.push_back(task));
|
||||
}
|
||||
|
||||
fn extend_roa_tasks<F>(&self, mut push: F)
|
||||
where
|
||||
F: FnMut(OwnedRoaTask),
|
||||
{
|
||||
let shared = self.shared.clone();
|
||||
self.locked_files()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, file)| file.rsync_uri.ends_with(".roa"))
|
||||
.map(|(index, file)| OwnedRoaTask {
|
||||
publication_point_id: self.publication_point_id,
|
||||
index,
|
||||
file: file.clone(),
|
||||
manifest_rsync_uri: self.manifest_rsync_uri.clone(),
|
||||
issuer_ca_der: self.issuer_ca_der.clone(),
|
||||
issuer_ca: self.issuer_ca.clone(),
|
||||
issuer_spki_der: self.issuer_spki_der.clone(),
|
||||
issuer_ca_rsync_uri: self.issuer_ca_rsync_uri.clone(),
|
||||
crl_cache: self.crl_cache.clone(),
|
||||
issuer_resources_index: self.issuer_resources_index.clone(),
|
||||
issuer_effective_ip: self.issuer_effective_ip.clone(),
|
||||
issuer_effective_as: self.issuer_effective_as.clone(),
|
||||
validation_time: self.validation_time,
|
||||
collect_vcir_local_outputs: self.collect_vcir_local_outputs,
|
||||
strict_cms_der: self.strict_cms_der,
|
||||
strict_name: self.strict_name,
|
||||
submitted_at: None,
|
||||
})
|
||||
.collect()
|
||||
.for_each(|(index, _)| {
|
||||
push(OwnedRoaTask {
|
||||
publication_point_id: self.publication_point_id,
|
||||
index,
|
||||
shared: shared.clone(),
|
||||
validation_time: self.validation_time,
|
||||
collect_vcir_local_outputs: self.collect_vcir_local_outputs,
|
||||
strict_cms_der: self.strict_cms_der,
|
||||
strict_name: self.strict_name,
|
||||
submitted_at: None,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn roa_task_count(&self) -> usize {
|
||||
@@ -991,7 +1001,11 @@ impl ParallelObjectsStage {
|
||||
}
|
||||
|
||||
pub(crate) fn locked_file_count(&self) -> usize {
|
||||
self.locked_files.len()
|
||||
self.shared.locked_files.len()
|
||||
}
|
||||
|
||||
fn locked_files(&self) -> &[PackFile] {
|
||||
self.shared.locked_files.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1212,19 +1226,21 @@ pub(crate) fn prepare_publication_point_for_parallel_roa<P: PublicationPointData
|
||||
|
||||
ParallelObjectsPrepare::Staged(ParallelObjectsStage {
|
||||
publication_point_id,
|
||||
locked_files: locked_files.to_vec(),
|
||||
manifest_rsync_uri: manifest_rsync_uri.to_string(),
|
||||
issuer_ca_der: Arc::<[u8]>::from(issuer_ca_der.to_vec()),
|
||||
issuer_spki_der: Arc::<[u8]>::from(issuer_ca.tbs.subject_public_key_info.clone()),
|
||||
issuer_ca: Arc::new(issuer_ca),
|
||||
issuer_ca_rsync_uri: issuer_ca_rsync_uri.map(ToString::to_string),
|
||||
crl_cache: Arc::new(Mutex::new(crl_cache)),
|
||||
issuer_resources_index: Arc::new(build_issuer_resources_index(
|
||||
issuer_effective_ip,
|
||||
issuer_effective_as,
|
||||
)),
|
||||
issuer_effective_ip: issuer_effective_ip.cloned(),
|
||||
issuer_effective_as: issuer_effective_as.cloned(),
|
||||
shared: Arc::new(RoaTaskShared {
|
||||
locked_files: Arc::<[PackFile]>::from(locked_files.to_vec()),
|
||||
manifest_rsync_uri: Arc::<str>::from(manifest_rsync_uri),
|
||||
issuer_ca_der: Arc::<[u8]>::from(issuer_ca_der.to_vec()),
|
||||
issuer_spki_der: Arc::<[u8]>::from(issuer_ca.tbs.subject_public_key_info.clone()),
|
||||
issuer_ca: Arc::new(issuer_ca),
|
||||
issuer_ca_rsync_uri: issuer_ca_rsync_uri.map(Arc::<str>::from),
|
||||
crl_cache: Arc::new(Mutex::new(crl_cache)),
|
||||
issuer_resources_index: Arc::new(build_issuer_resources_index(
|
||||
issuer_effective_ip,
|
||||
issuer_effective_as,
|
||||
)),
|
||||
issuer_effective_ip: issuer_effective_ip.cloned().map(Arc::new),
|
||||
issuer_effective_as: issuer_effective_as.cloned().map(Arc::new),
|
||||
}),
|
||||
validation_time,
|
||||
collect_vcir_local_outputs,
|
||||
strict_cms_der: policy.strict.cms_der,
|
||||
@@ -1241,18 +1257,20 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
timing: Option<&TimingHandle>,
|
||||
) -> Result<ObjectsOutput, String> {
|
||||
roa_results.sort_by_key(|result| result.index);
|
||||
let mut roa_by_index = roa_results
|
||||
.into_iter()
|
||||
.map(|result| (result.index, result))
|
||||
.collect::<std::collections::HashMap<_, _>>();
|
||||
let mut aspa_crl_cache = stage
|
||||
let mut roa_results = roa_results.into_iter().peekable();
|
||||
let shared = stage.shared.clone();
|
||||
let mut aspa_crl_cache = shared
|
||||
.crl_cache
|
||||
.lock()
|
||||
.expect("parallel ROA CRL cache lock")
|
||||
.clone();
|
||||
let issuer_spki = SubjectPublicKeyInfo::from_der(stage.issuer_spki_der.as_ref())
|
||||
let issuer_spki = SubjectPublicKeyInfo::from_der(shared.issuer_spki_der.as_ref())
|
||||
.map_err(|e| e.to_string())?
|
||||
.1;
|
||||
let collect_vcir_local_outputs = stage.collect_vcir_local_outputs;
|
||||
let validation_time = stage.validation_time;
|
||||
let strict_cms_der = stage.strict_cms_der;
|
||||
let strict_name = stage.strict_name;
|
||||
let mut stats = stage.stats;
|
||||
let mut warnings = stage.warnings;
|
||||
let mut audit = stage.audit;
|
||||
@@ -1260,21 +1278,32 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
let mut aspas: Vec<AspaAttestation> = Vec::new();
|
||||
let mut local_outputs_cache: Vec<VcirLocalOutput> = Vec::new();
|
||||
|
||||
for (idx, file) in stage.locked_files.iter().enumerate() {
|
||||
for (idx, file) in shared.locked_files.iter().enumerate() {
|
||||
if file.rsync_uri.ends_with(".roa") {
|
||||
let result = roa_by_index
|
||||
.remove(&idx)
|
||||
.ok_or_else(|| format!("missing ROA task result for {}", file.rsync_uri))?;
|
||||
let result = match roa_results.peek() {
|
||||
Some(result) if result.index == idx => roa_results
|
||||
.next()
|
||||
.expect("peeked ROA task result must be present"),
|
||||
Some(result) => {
|
||||
return Err(format!(
|
||||
"unexpected ROA task result index {} while reducing {} at index {}",
|
||||
result.index, file.rsync_uri, idx
|
||||
));
|
||||
}
|
||||
None => {
|
||||
return Err(format!("missing ROA task result for {}", file.rsync_uri));
|
||||
}
|
||||
};
|
||||
match result.outcome {
|
||||
Ok(mut ok) => {
|
||||
stats.roa_ok += 1;
|
||||
vrps.append(&mut ok.vrps);
|
||||
if stage.collect_vcir_local_outputs {
|
||||
if collect_vcir_local_outputs {
|
||||
local_outputs_cache.extend(ok.local_outputs);
|
||||
}
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: result.rsync_uri,
|
||||
sha256_hex: result.sha256_hex,
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
kind: AuditObjectKind::Roa,
|
||||
result: AuditObjectResult::Ok,
|
||||
detail: None,
|
||||
@@ -1282,8 +1311,8 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
}
|
||||
Err(e) => {
|
||||
audit.push(ObjectAuditEntry {
|
||||
rsync_uri: result.rsync_uri.clone(),
|
||||
sha256_hex: result.sha256_hex,
|
||||
rsync_uri: file.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&file.sha256),
|
||||
kind: AuditObjectKind::Roa,
|
||||
result: AuditObjectResult::Error,
|
||||
detail: Some(e.to_string()),
|
||||
@@ -1291,9 +1320,9 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
let mut refs = vec![RfcRef("RFC 6488 §3"), RfcRef("RFC 9582 §4-§5")];
|
||||
refs.extend_from_slice(extra_rfc_refs_for_crl_selection(&e));
|
||||
warnings.push(
|
||||
Warning::new(format!("dropping invalid ROA: {}: {e}", result.rsync_uri))
|
||||
Warning::new(format!("dropping invalid ROA: {}: {e}", file.rsync_uri))
|
||||
.with_rfc_refs(&refs)
|
||||
.with_context(&result.rsync_uri),
|
||||
.with_context(&file.rsync_uri),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1301,20 +1330,20 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
let _t = timing.as_ref().map(|t| t.span_phase("objects_aspa_total"));
|
||||
match process_aspa_with_issuer(
|
||||
file,
|
||||
&stage.manifest_rsync_uri,
|
||||
stage.issuer_ca_der.as_ref(),
|
||||
stage.issuer_ca.as_ref(),
|
||||
shared.manifest_rsync_uri.as_ref(),
|
||||
shared.issuer_ca_der.as_ref(),
|
||||
shared.issuer_ca.as_ref(),
|
||||
&issuer_spki,
|
||||
stage.issuer_ca_rsync_uri.as_deref(),
|
||||
shared.issuer_ca_rsync_uri.as_deref(),
|
||||
&mut aspa_crl_cache,
|
||||
stage.issuer_resources_index.as_ref(),
|
||||
stage.issuer_effective_ip.as_ref(),
|
||||
stage.issuer_effective_as.as_ref(),
|
||||
stage.validation_time,
|
||||
shared.issuer_resources_index.as_ref(),
|
||||
shared.issuer_effective_ip.as_deref(),
|
||||
shared.issuer_effective_as.as_deref(),
|
||||
validation_time,
|
||||
timing,
|
||||
stage.collect_vcir_local_outputs,
|
||||
stage.strict_cms_der,
|
||||
stage.strict_name,
|
||||
collect_vcir_local_outputs,
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
) {
|
||||
Ok((att, local_output)) => {
|
||||
stats.aspa_ok += 1;
|
||||
@@ -1349,6 +1378,12 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(result) = roa_results.next() {
|
||||
return Err(format!(
|
||||
"unexpected trailing ROA task result at index {}",
|
||||
result.index
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ObjectsOutput {
|
||||
vrps,
|
||||
@@ -1388,8 +1423,9 @@ fn process_publication_point_for_issuer_parallel_roa_inner<P: PublicationPointDa
|
||||
ParallelObjectsPrepare::Staged(stage) => stage,
|
||||
};
|
||||
|
||||
let mut pending = std::collections::VecDeque::from(stage.build_roa_tasks());
|
||||
let roa_task_count = stage.roa_task_count();
|
||||
let mut pending = std::collections::VecDeque::with_capacity(roa_task_count);
|
||||
stage.append_roa_tasks_to(&mut pending);
|
||||
let mut worker_pool = pool
|
||||
.pool
|
||||
.lock()
|
||||
@@ -1537,7 +1573,6 @@ pub(crate) fn validate_roa_task_serial(
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
) -> RoaTaskResult {
|
||||
let sha256_hex = sha256_hex_from_32(&task.file.sha256);
|
||||
let outcome = process_roa_with_issuer(
|
||||
task.file,
|
||||
manifest_rsync_uri,
|
||||
@@ -1566,15 +1601,13 @@ pub(crate) fn validate_roa_task_serial(
|
||||
worker_index: 0,
|
||||
queue_wait_ms: 0,
|
||||
worker_ms: 0,
|
||||
rsync_uri: task.file.rsync_uri.clone(),
|
||||
sha256_hex,
|
||||
outcome,
|
||||
}
|
||||
}
|
||||
|
||||
fn process_roa_with_issuer(
|
||||
file: &PackFile,
|
||||
manifest_rsync_uri: &str,
|
||||
_manifest_rsync_uri: &str,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca: &ResourceCertificate,
|
||||
issuer_spki: &SubjectPublicKeyInfo<'_>,
|
||||
@@ -1659,12 +1692,6 @@ fn process_roa_with_issuer(
|
||||
.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:{}:{}:{}:{}",
|
||||
@@ -1673,20 +1700,20 @@ fn process_roa_with_issuer(
|
||||
.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(),
|
||||
],
|
||||
source_object_type: VcirSourceObjectType::Roa,
|
||||
source_object_hash: file.sha256,
|
||||
source_ee_cert_hash: sha256_hex_to_32(&source_ee_cert_hash),
|
||||
payload: VcirLocalOutputPayload::Vrp {
|
||||
asn: vrp.asn,
|
||||
afi: vrp.prefix.afi,
|
||||
prefix_len: vrp.prefix.prefix_len,
|
||||
addr: vrp.prefix.addr,
|
||||
max_length: vrp.max_length,
|
||||
},
|
||||
rule_hash: sha256_hex_to_32(&rule_hash),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@@ -1696,7 +1723,7 @@ fn process_roa_with_issuer(
|
||||
|
||||
fn process_roa_with_issuer_parallel_cached(
|
||||
file: &PackFile,
|
||||
manifest_rsync_uri: &str,
|
||||
_manifest_rsync_uri: &str,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca: &ResourceCertificate,
|
||||
issuer_spki: &SubjectPublicKeyInfo<'_>,
|
||||
@@ -1787,12 +1814,6 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
.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:{}:{}:{}:{}",
|
||||
@@ -1801,20 +1822,20 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
.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(),
|
||||
],
|
||||
source_object_type: VcirSourceObjectType::Roa,
|
||||
source_object_hash: file.sha256,
|
||||
source_ee_cert_hash: sha256_hex_to_32(&source_ee_cert_hash),
|
||||
payload: VcirLocalOutputPayload::Vrp {
|
||||
asn: vrp.asn,
|
||||
afi: vrp.prefix.afi,
|
||||
prefix_len: vrp.prefix.prefix_len,
|
||||
addr: vrp.prefix.addr,
|
||||
max_length: vrp.max_length,
|
||||
},
|
||||
rule_hash: sha256_hex_to_32(&rule_hash),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@@ -1824,7 +1845,7 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
|
||||
fn process_aspa_with_issuer(
|
||||
file: &PackFile,
|
||||
manifest_rsync_uri: &str,
|
||||
_manifest_rsync_uri: &str,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca: &ResourceCertificate,
|
||||
issuer_spki: &SubjectPublicKeyInfo<'_>,
|
||||
@@ -1922,24 +1943,17 @@ fn process_aspa_with_issuer(
|
||||
.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,
|
||||
],
|
||||
source_object_type: VcirSourceObjectType::Aspa,
|
||||
source_object_hash: file.sha256,
|
||||
source_ee_cert_hash: sha256_hex_to_32(&source_ee_cert_hash),
|
||||
payload: VcirLocalOutputPayload::Aspa {
|
||||
customer_as_id: attestation.customer_as_id,
|
||||
provider_as_ids: attestation.provider_as_ids.clone(),
|
||||
},
|
||||
rule_hash: sha256_hex_to_32(&rule_hash),
|
||||
};
|
||||
|
||||
Ok((attestation, Some(local_output)))
|
||||
@@ -2965,6 +2979,54 @@ mod tests {
|
||||
assert_eq!(roa_afi_to_string(RoaAfi::Ipv6), "ipv6");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parallel_stage_roa_tasks_share_stage_owned_payloads() {
|
||||
let stage = ParallelObjectsStage {
|
||||
publication_point_id: 7,
|
||||
shared: Arc::new(RoaTaskShared {
|
||||
locked_files: Arc::<[PackFile]>::from(vec![
|
||||
PackFile::from_bytes_with_sha256(
|
||||
"rsync://example.test/repo/a.roa",
|
||||
vec![1, 2, 3],
|
||||
[1u8; 32],
|
||||
),
|
||||
PackFile::from_bytes_with_sha256(
|
||||
"rsync://example.test/repo/b.roa",
|
||||
vec![4, 5, 6],
|
||||
[2u8; 32],
|
||||
),
|
||||
]),
|
||||
manifest_rsync_uri: Arc::<str>::from("rsync://example.test/repo/manifest.mft"),
|
||||
issuer_ca_der: Arc::from([0x01u8].as_slice()),
|
||||
issuer_ca: Arc::new(
|
||||
ResourceCertificate::decode_der(&fixture_bytes(
|
||||
"tests/fixtures/ta/apnic-ta.cer",
|
||||
))
|
||||
.expect("decode fixture CA certificate"),
|
||||
),
|
||||
issuer_spki_der: Arc::from([0x02u8].as_slice()),
|
||||
issuer_ca_rsync_uri: Some(Arc::<str>::from("rsync://example.test/repo/ca.cer")),
|
||||
crl_cache: Arc::new(Mutex::new(HashMap::new())),
|
||||
issuer_resources_index: Arc::new(IssuerResourcesIndex::default()),
|
||||
issuer_effective_ip: None,
|
||||
issuer_effective_as: None,
|
||||
}),
|
||||
validation_time: OffsetDateTime::now_utc(),
|
||||
collect_vcir_local_outputs: false,
|
||||
strict_cms_der: false,
|
||||
strict_name: false,
|
||||
warnings: Vec::new(),
|
||||
stats: ObjectsStats {
|
||||
roa_total: 2,
|
||||
..ObjectsStats::default()
|
||||
},
|
||||
audit: Vec::new(),
|
||||
};
|
||||
let tasks = stage.build_roa_tasks();
|
||||
assert_eq!(tasks.len(), 2);
|
||||
assert!(Arc::ptr_eq(&tasks[0].shared, &tasks[1].shared));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn strict_name_manifest_decode_failure_drops_publication_point() {
|
||||
let publication_point = PublicationPointSnapshot {
|
||||
|
||||
Reference in New Issue
Block a user