20260828 收口Feature151 TA constraints优化与验证
This commit is contained in:
@@ -961,6 +961,38 @@ pub fn process_publication_point_for_issuer_with_cache_options<P: PublicationPoi
|
||||
timing: Option<&TimingHandle>,
|
||||
collect_vcir_local_outputs: bool,
|
||||
roa_cache: RoaValidationCacheInput<'_>,
|
||||
) -> ObjectsOutput {
|
||||
process_publication_point_for_issuer_with_cache_options_and_ta_constraints(
|
||||
publication_point,
|
||||
policy,
|
||||
issuer_ca_der,
|
||||
issuer_ca_rsync_uri,
|
||||
issuer_effective_ip,
|
||||
issuer_effective_as,
|
||||
validation_time,
|
||||
timing,
|
||||
collect_vcir_local_outputs,
|
||||
roa_cache,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
/// Serial signed-object processing with an optional, locally configured
|
||||
/// constraint set for the TA that owns this publication-point tree.
|
||||
pub fn process_publication_point_for_issuer_with_cache_options_and_ta_constraints<
|
||||
P: PublicationPointData,
|
||||
>(
|
||||
publication_point: &P,
|
||||
policy: &Policy,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca_rsync_uri: Option<&str>,
|
||||
issuer_effective_ip: Option<&crate::data_model::rc::IpResourceSet>,
|
||||
issuer_effective_as: Option<&crate::data_model::rc::AsResourceSet>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
collect_vcir_local_outputs: bool,
|
||||
roa_cache: RoaValidationCacheInput<'_>,
|
||||
ta_constraints: Option<&crate::ta_constraints::TaConstraints>,
|
||||
) -> ObjectsOutput {
|
||||
let manifest_rsync_uri = publication_point.manifest_rsync_uri();
|
||||
let manifest_bytes = publication_point.manifest_bytes();
|
||||
@@ -1271,6 +1303,7 @@ pub fn process_publication_point_for_issuer_with_cache_options<P: PublicationPoi
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
policy.resource_validation_mode,
|
||||
ta_constraints,
|
||||
)
|
||||
}
|
||||
blocked @ (RoaCacheLookupResult::HashBlocked
|
||||
@@ -1297,6 +1330,7 @@ pub fn process_publication_point_for_issuer_with_cache_options<P: PublicationPoi
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
policy.resource_validation_mode,
|
||||
ta_constraints,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1320,6 +1354,7 @@ pub fn process_publication_point_for_issuer_with_cache_options<P: PublicationPoi
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
policy.resource_validation_mode,
|
||||
ta_constraints,
|
||||
)
|
||||
};
|
||||
match result.outcome {
|
||||
@@ -1437,6 +1472,7 @@ pub fn process_publication_point_for_issuer_with_cache_options<P: PublicationPoi
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
policy.resource_validation_mode,
|
||||
ta_constraints,
|
||||
) {
|
||||
Ok((att, local_output)) => {
|
||||
stats.aspa_ok += 1;
|
||||
@@ -1790,6 +1826,10 @@ pub(crate) struct RoaTaskShared {
|
||||
issuer_effective_ip: Option<Arc<crate::data_model::rc::IpResourceSet>>,
|
||||
issuer_effective_as: Option<Arc<crate::data_model::rc::AsResourceSet>>,
|
||||
resource_validation_mode: ResourceValidationMode,
|
||||
/// Immutable constraints snapshot selected by the owning TAL. Every
|
||||
/// ROA task for a publication point shares this Arc, so workers do not
|
||||
/// need a mutable/global policy lookup or a copy of the interval rules.
|
||||
ta_constraints: Option<Arc<crate::ta_constraints::TaConstraints>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -1911,6 +1951,7 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
task.strict_cms_der,
|
||||
task.strict_name,
|
||||
task.resource_validation_mode,
|
||||
shared.ta_constraints.as_deref(),
|
||||
)
|
||||
.map(|(vrps, local_outputs, cache_object_meta)| RoaTaskOk {
|
||||
vrps,
|
||||
@@ -2009,6 +2050,40 @@ pub(crate) fn prepare_publication_point_for_parallel_roa_with_cache<P: Publicati
|
||||
validation_time: time::OffsetDateTime,
|
||||
collect_vcir_local_outputs: bool,
|
||||
roa_cache: RoaValidationCacheInput<'_>,
|
||||
) -> ParallelObjectsPrepare {
|
||||
prepare_publication_point_for_parallel_roa_with_cache_and_ta_constraints(
|
||||
publication_point_id,
|
||||
publication_point,
|
||||
policy,
|
||||
issuer_ca_der,
|
||||
issuer_ca_rsync_uri,
|
||||
issuer_effective_ip,
|
||||
issuer_effective_as,
|
||||
validation_time,
|
||||
collect_vcir_local_outputs,
|
||||
roa_cache,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
/// Prepare a publication point for parallel ROA validation with the
|
||||
/// immutable constraints snapshot belonging to its TAL. The snapshot is
|
||||
/// moved into the stage-owned shared payload and therefore remains available
|
||||
/// to detached ROA workers after the scoped phase-2 stage worker returns.
|
||||
pub(crate) fn prepare_publication_point_for_parallel_roa_with_cache_and_ta_constraints<
|
||||
P: PublicationPointData,
|
||||
>(
|
||||
publication_point_id: u64,
|
||||
publication_point: &P,
|
||||
policy: &Policy,
|
||||
issuer_ca_der: &[u8],
|
||||
issuer_ca_rsync_uri: Option<&str>,
|
||||
issuer_effective_ip: Option<&crate::data_model::rc::IpResourceSet>,
|
||||
issuer_effective_as: Option<&crate::data_model::rc::AsResourceSet>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
collect_vcir_local_outputs: bool,
|
||||
roa_cache: RoaValidationCacheInput<'_>,
|
||||
ta_constraints: Option<Arc<crate::ta_constraints::TaConstraints>>,
|
||||
) -> ParallelObjectsPrepare {
|
||||
let manifest_rsync_uri = publication_point.manifest_rsync_uri();
|
||||
let manifest_bytes = publication_point.manifest_bytes();
|
||||
@@ -2323,6 +2398,7 @@ pub(crate) fn prepare_publication_point_for_parallel_roa_with_cache<P: Publicati
|
||||
issuer_effective_ip: issuer_effective_ip.cloned().map(Arc::new),
|
||||
issuer_effective_as: issuer_effective_as.cloned().map(Arc::new),
|
||||
resource_validation_mode: policy.resource_validation_mode,
|
||||
ta_constraints,
|
||||
}),
|
||||
validation_time,
|
||||
collect_vcir_local_outputs,
|
||||
@@ -2441,6 +2517,7 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
shared.resource_validation_mode,
|
||||
shared.ta_constraints.as_deref(),
|
||||
) {
|
||||
Ok((att, local_output)) => {
|
||||
stats.aspa_ok += 1;
|
||||
@@ -2660,6 +2737,9 @@ pub(crate) enum ObjectValidateError {
|
||||
"EE certificate resources are not a subset of issuer effective resources (RFC 6487 §7.2; RFC 3779)"
|
||||
)]
|
||||
EeResourcesNotSubset,
|
||||
|
||||
#[error("EE certificate violates locally configured TA constraints: {0}")]
|
||||
TaConstraints(#[from] crate::ta_constraints::TaConstraintsViolation),
|
||||
}
|
||||
|
||||
pub(crate) fn validate_roa_task_serial(
|
||||
@@ -2679,6 +2759,7 @@ pub(crate) fn validate_roa_task_serial(
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
resource_validation_mode: ResourceValidationMode,
|
||||
ta_constraints: Option<&crate::ta_constraints::TaConstraints>,
|
||||
) -> RoaTaskResult {
|
||||
let outcome = process_roa_with_issuer(
|
||||
task.file,
|
||||
@@ -2697,6 +2778,7 @@ pub(crate) fn validate_roa_task_serial(
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
resource_validation_mode,
|
||||
ta_constraints,
|
||||
)
|
||||
.map(|(vrps, local_outputs, cache_object_meta)| RoaTaskOk {
|
||||
vrps,
|
||||
@@ -2732,6 +2814,7 @@ fn process_roa_with_issuer(
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
resource_validation_mode: ResourceValidationMode,
|
||||
ta_constraints: Option<&crate::ta_constraints::TaConstraints>,
|
||||
) -> Result<(Vec<Vrp>, Vec<VcirLocalOutput>, Option<RoaCacheObjectMeta>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
@@ -2792,6 +2875,10 @@ fn process_roa_with_issuer(
|
||||
)?;
|
||||
drop(_subset);
|
||||
|
||||
if let Some(ta_constraints) = ta_constraints {
|
||||
ta_constraints.validate_ee_certificate(&ee.resource_cert)?;
|
||||
}
|
||||
|
||||
let vrps = roa_to_vrps_with_vrs(&roa, ee_vrs.ip.as_ref())?;
|
||||
let cache_object_meta = RoaCacheObjectMeta {
|
||||
source_object_uri: file.rsync_uri.clone(),
|
||||
@@ -2861,6 +2948,7 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
resource_validation_mode: ResourceValidationMode,
|
||||
ta_constraints: Option<&crate::ta_constraints::TaConstraints>,
|
||||
) -> Result<(Vec<Vrp>, Vec<VcirLocalOutput>, Option<RoaCacheObjectMeta>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
@@ -2927,6 +3015,10 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
)?;
|
||||
drop(_subset);
|
||||
|
||||
if let Some(ta_constraints) = ta_constraints {
|
||||
ta_constraints.validate_ee_certificate(&ee.resource_cert)?;
|
||||
}
|
||||
|
||||
let vrps = roa_to_vrps_with_vrs(&roa, ee_vrs.ip.as_ref())?;
|
||||
let cache_object_meta = RoaCacheObjectMeta {
|
||||
source_object_uri: file.rsync_uri.clone(),
|
||||
@@ -2996,6 +3088,7 @@ fn process_aspa_with_issuer(
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
resource_validation_mode: ResourceValidationMode,
|
||||
ta_constraints: Option<&crate::ta_constraints::TaConstraints>,
|
||||
) -> Result<(AspaAttestation, Option<VcirLocalOutput>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
@@ -3056,6 +3149,10 @@ fn process_aspa_with_issuer(
|
||||
)?;
|
||||
drop(_subset);
|
||||
|
||||
if let Some(ta_constraints) = ta_constraints {
|
||||
ta_constraints.validate_ee_certificate(&ee.resource_cert)?;
|
||||
}
|
||||
|
||||
validate_aspa_customer_in_vrs(&aspa, ee_vrs.asn.as_ref())?;
|
||||
|
||||
let attestation = AspaAttestation {
|
||||
@@ -5505,6 +5602,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parallel_stage_roa_tasks_share_stage_owned_payloads() {
|
||||
let ta_constraints = Arc::new(
|
||||
crate::ta_constraints::TaConstraints::from_file(
|
||||
&std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("tests/fixtures/ta_constraints/afrinic-current-ipv4-deny.constraints"),
|
||||
)
|
||||
.expect("load constraints fixture"),
|
||||
);
|
||||
let stage = ParallelObjectsStage {
|
||||
publication_point_id: 7,
|
||||
shared: Arc::new(RoaTaskShared {
|
||||
@@ -5535,6 +5639,7 @@ mod tests {
|
||||
issuer_effective_ip: None,
|
||||
issuer_effective_as: None,
|
||||
resource_validation_mode: ResourceValidationMode::default(),
|
||||
ta_constraints: Some(Arc::clone(&ta_constraints)),
|
||||
}),
|
||||
validation_time: OffsetDateTime::now_utc(),
|
||||
collect_vcir_local_outputs: false,
|
||||
@@ -5554,6 +5659,14 @@ mod tests {
|
||||
let tasks = stage.build_roa_tasks();
|
||||
assert_eq!(tasks.len(), 2);
|
||||
assert!(Arc::ptr_eq(&tasks[0].shared, &tasks[1].shared));
|
||||
assert!(Arc::ptr_eq(
|
||||
tasks[0]
|
||||
.shared
|
||||
.ta_constraints
|
||||
.as_ref()
|
||||
.expect("task constraints snapshot"),
|
||||
&ta_constraints
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -901,6 +901,10 @@ where
|
||||
H: Fetcher + Clone + 'static,
|
||||
R: crate::fetch::rsync::RsyncFetcher + Clone + 'static,
|
||||
{
|
||||
// Constraints are an immutable per-run policy snapshot. The phase-2
|
||||
// ready-stage binds the snapshot to each CA's TAL and moves an Arc into
|
||||
// ROA/ASPA worker state, so constrained multi-TAL runs retain the same
|
||||
// parallel scheduler as unconstrained runs.
|
||||
let phase2_enabled = phase2_config.is_some();
|
||||
if tal_inputs.is_empty() {
|
||||
return Err(RunTreeFromTalError::Replay(
|
||||
|
||||
@@ -16,7 +16,8 @@ use crate::validation::manifest::PublicationPointData;
|
||||
use crate::validation::manifest::PublicationPointSource;
|
||||
use crate::validation::objects::{
|
||||
ObjectsOutput, OwnedRoaTask, ParallelObjectsPrepare, ParallelObjectsStage,
|
||||
RoaValidationCacheInput, prepare_publication_point_for_parallel_roa_with_cache,
|
||||
RoaValidationCacheInput,
|
||||
prepare_publication_point_for_parallel_roa_with_cache_and_ta_constraints,
|
||||
reduce_parallel_roa_stage,
|
||||
};
|
||||
use crate::validation::tree::{
|
||||
@@ -1367,7 +1368,16 @@ fn compute_ready_publication_point_stage(
|
||||
} else {
|
||||
RoaValidationCacheInput::disabled()
|
||||
};
|
||||
match prepare_publication_point_for_parallel_roa_with_cache(
|
||||
let ta_constraints = runner
|
||||
.policy
|
||||
.ta_constraints
|
||||
.shared_for_tal(&ready.node.handle.tal_id);
|
||||
if ta_constraints.is_some() {
|
||||
if let Some(timing) = runner.timing.as_ref() {
|
||||
timing.record_count("ta_constraints_parallel_publication_points", 1);
|
||||
}
|
||||
}
|
||||
match prepare_publication_point_for_parallel_roa_with_cache_and_ta_constraints(
|
||||
ready.node.id,
|
||||
&fresh_stage.fresh_point,
|
||||
runner.policy,
|
||||
@@ -1378,6 +1388,7 @@ fn compute_ready_publication_point_stage(
|
||||
runner.validation_time,
|
||||
runner.persist_vcir,
|
||||
roa_cache,
|
||||
ta_constraints,
|
||||
) {
|
||||
ParallelObjectsPrepare::Complete(mut objects) => {
|
||||
metrics.prepare_ms = elapsed_ms(prepare_started);
|
||||
|
||||
@@ -53,6 +53,7 @@ use crate::validation::objects::{
|
||||
AspaAttestation, ParallelRoaWorkerPool, RoaValidationCacheInput, RoaValidationCacheView,
|
||||
RouterKeyPayload, Vrp, process_publication_point_for_issuer_parallel_roa_with_cache_options,
|
||||
process_publication_point_for_issuer_parallel_roa_with_pool_cache_options,
|
||||
process_publication_point_for_issuer_with_cache_options_and_ta_constraints,
|
||||
};
|
||||
use crate::validation::publication_point::PublicationPointSnapshot;
|
||||
use crate::validation::tree::{
|
||||
@@ -1551,12 +1552,30 @@ impl<'a> PublicationPointRunner for Rpkiv1PublicationPointRunner<'a> {
|
||||
RoaValidationCacheInput::disabled()
|
||||
};
|
||||
let objects_processing_started = std::time::Instant::now();
|
||||
let ta_constraints = self.policy.ta_constraints.for_tal(&ca.tal_id);
|
||||
let mut objects = {
|
||||
let _objects_total = self
|
||||
.timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_processing_total"));
|
||||
if let Some(phase2_pool) = self.parallel_roa_worker_pool.as_ref() {
|
||||
if let Some(ta_constraints) = ta_constraints {
|
||||
// This method is the serial/fallback publication-point path. The
|
||||
// phase-2 scheduler uses the stage-specific parallel prepare path,
|
||||
// which carries the same immutable per-TAL snapshot into workers.
|
||||
process_publication_point_for_issuer_with_cache_options_and_ta_constraints(
|
||||
&fresh_point,
|
||||
self.policy,
|
||||
issuer_ca_der.as_ref(),
|
||||
ca.ca_certificate_rsync_uri.as_deref(),
|
||||
ca.effective_ip_resources.as_ref(),
|
||||
ca.effective_as_resources.as_ref(),
|
||||
self.validation_time,
|
||||
self.timing.as_ref(),
|
||||
false,
|
||||
roa_cache,
|
||||
Some(ta_constraints),
|
||||
)
|
||||
} else if let Some(phase2_pool) = self.parallel_roa_worker_pool.as_ref() {
|
||||
process_publication_point_for_issuer_parallel_roa_with_pool_cache_options(
|
||||
&fresh_point,
|
||||
self.policy,
|
||||
@@ -1971,13 +1990,13 @@ fn sha256_digest_32(bytes: impl AsRef<[u8]>) -> [u8; 32] {
|
||||
out
|
||||
}
|
||||
|
||||
fn hash_serialized_parts(parts: &[(&str, Vec<u8>)]) -> [u8; 32] {
|
||||
fn hash_serialized_parts(parts: &[(&str, &[u8])]) -> [u8; 32] {
|
||||
let mut hasher = sha2::Sha256::new();
|
||||
for (label, value) in parts {
|
||||
hasher.update((label.len() as u64).to_be_bytes());
|
||||
hasher.update(label.as_bytes());
|
||||
hasher.update((value.len() as u64).to_be_bytes());
|
||||
hasher.update(value);
|
||||
hasher.update(*value);
|
||||
}
|
||||
let digest = hasher.finalize();
|
||||
let mut out = [0u8; 32];
|
||||
@@ -1991,41 +2010,34 @@ fn cbor_or_debug_bytes<T: serde::Serialize + std::fmt::Debug>(value: &T) -> Vec<
|
||||
|
||||
fn ta_context_digest_for_ca(ca: &CaInstanceHandle) -> [u8; 32] {
|
||||
hash_serialized_parts(&[
|
||||
("version", b"publication-point-cache-ta-v1".to_vec()),
|
||||
("tal_id", ca.tal_id.as_bytes().to_vec()),
|
||||
("version", b"publication-point-cache-ta-v1"),
|
||||
("tal_id", ca.tal_id.as_bytes()),
|
||||
])
|
||||
}
|
||||
|
||||
pub(crate) fn ca_validation_context_digest_for_ca(ca: &CaInstanceHandle) -> [u8; 32] {
|
||||
let parent_manifest = ca
|
||||
.parent_manifest_rsync_uri
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.as_bytes();
|
||||
let effective_ip = cbor_or_debug_bytes(&ca.effective_ip_resources);
|
||||
let effective_as = cbor_or_debug_bytes(&ca.effective_as_resources);
|
||||
hash_serialized_parts(&[
|
||||
(
|
||||
"version",
|
||||
b"publication-point-cache-parent-context-v1".to_vec(),
|
||||
),
|
||||
("tal_id", ca.tal_id.as_bytes().to_vec()),
|
||||
(
|
||||
"parent_manifest",
|
||||
ca.parent_manifest_rsync_uri
|
||||
.as_deref()
|
||||
.unwrap_or("")
|
||||
.as_bytes()
|
||||
.to_vec(),
|
||||
),
|
||||
(
|
||||
"effective_ip",
|
||||
cbor_or_debug_bytes(&ca.effective_ip_resources),
|
||||
),
|
||||
(
|
||||
"effective_as",
|
||||
cbor_or_debug_bytes(&ca.effective_as_resources),
|
||||
),
|
||||
("version", b"publication-point-cache-parent-context-v1"),
|
||||
("tal_id", ca.tal_id.as_bytes()),
|
||||
("parent_manifest", parent_manifest),
|
||||
("effective_ip", effective_ip.as_slice()),
|
||||
("effective_as", effective_as.as_slice()),
|
||||
])
|
||||
}
|
||||
|
||||
pub(crate) fn publication_point_cache_policy_fingerprint(policy: &Policy) -> [u8; 32] {
|
||||
let policy_bytes = cbor_or_debug_bytes(policy);
|
||||
hash_serialized_parts(&[
|
||||
("version", b"publication-point-cache-policy-v1".to_vec()),
|
||||
("policy", cbor_or_debug_bytes(policy)),
|
||||
("version", b"publication-point-cache-policy-v3"),
|
||||
("policy", policy_bytes.as_slice()),
|
||||
("ta_constraints", policy.ta_constraints.fingerprint_bytes()),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -2084,16 +2096,13 @@ fn child_certificate_cache_key_sha256_hex(
|
||||
policy_fingerprint: &[u8; 32],
|
||||
) -> String {
|
||||
let digest = hash_serialized_parts(&[
|
||||
("version", b"child-certificate-cache-key-v1".to_vec()),
|
||||
("child_cert_uri", child_cert_uri.as_bytes().to_vec()),
|
||||
("child_cert_sha256", child_cert_sha256.to_vec()),
|
||||
("issuer_ca_sha256", issuer_ca_sha256.to_vec()),
|
||||
("version", b"child-certificate-cache-key-v1"),
|
||||
("child_cert_uri", child_cert_uri.as_bytes()),
|
||||
("child_cert_sha256", child_cert_sha256),
|
||||
("issuer_ca_sha256", issuer_ca_sha256),
|
||||
// Keep the persisted cache-key label stable; this change only renames Rust identifiers.
|
||||
(
|
||||
"parent_context_digest",
|
||||
ca_validation_context_digest.to_vec(),
|
||||
),
|
||||
("policy_fingerprint", policy_fingerprint.to_vec()),
|
||||
("parent_context_digest", ca_validation_context_digest),
|
||||
("policy_fingerprint", policy_fingerprint),
|
||||
]);
|
||||
sha256_hex_from_32(&digest)
|
||||
}
|
||||
@@ -2986,6 +2995,24 @@ fn discover_children_from_fresh_snapshot_with_audit_cached_with_issuer_der<
|
||||
|
||||
match router_result {
|
||||
Ok(router) => {
|
||||
if let Some(ta_constraints) = policy.ta_constraints.for_tal(&issuer.tal_id)
|
||||
{
|
||||
if let Err(error) =
|
||||
ta_constraints.validate_ee_certificate(&router.resource_cert)
|
||||
{
|
||||
router_error = router_error.saturating_add(1);
|
||||
audits.push(ObjectAuditEntry {
|
||||
rsync_uri: f.rsync_uri.clone(),
|
||||
sha256_hex: sha256_hex_from_32(&f.sha256),
|
||||
kind: AuditObjectKind::RouterCertificate,
|
||||
result: AuditObjectResult::Error,
|
||||
detail: Some(format!(
|
||||
"router certificate violates TA constraints: {error}"
|
||||
)),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let router_asns = match router_asns_for_resource_mode(
|
||||
&router.asns,
|
||||
issuer.effective_as_resources.as_ref(),
|
||||
|
||||
Reference in New Issue
Block a user