20260510 增加strict策略模式并隔离多TA失败
This commit is contained in:
@@ -57,10 +57,42 @@ pub fn discover_root_ca_instance_from_tal_url(
|
||||
discover_root_ca_instance_from_tal(http_fetcher, tal, Some(tal_url.to_string()))
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal_url_with_strict_name(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal_url: &str,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
let tal_bytes = http_fetcher
|
||||
.fetch(tal_url)
|
||||
.map_err(FromTalError::TalFetch)?;
|
||||
let tal = Tal::decode_bytes(&tal_bytes)?;
|
||||
discover_root_ca_instance_from_tal_with_strict_name(
|
||||
http_fetcher,
|
||||
tal,
|
||||
Some(tal_url.to_string()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
discover_root_ca_instance_from_tal_impl(http_fetcher, tal, tal_url, false)
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal_with_strict_name(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
discover_root_ca_instance_from_tal_impl(http_fetcher, tal, tal_url, true)
|
||||
}
|
||||
|
||||
fn discover_root_ca_instance_from_tal_impl(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
strict_name: bool,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
if tal.ta_uris.is_empty() {
|
||||
return Err(FromTalError::NoTaUris);
|
||||
@@ -76,13 +108,14 @@ pub fn discover_root_ca_instance_from_tal(
|
||||
}
|
||||
};
|
||||
|
||||
let trust_anchor = match TrustAnchor::bind_der(tal.clone(), &ta_der, Some(ta_uri)) {
|
||||
Ok(ta) => ta,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("bind {ta_uri} failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let trust_anchor =
|
||||
match bind_trust_anchor_der(tal.clone(), &ta_der, Some(ta_uri), strict_name) {
|
||||
Ok(ta) => ta,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("bind {ta_uri} failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let ca_instance =
|
||||
match ca_instance_uris_from_ca_certificate(&trust_anchor.ta_certificate.rc_ca) {
|
||||
@@ -110,6 +143,37 @@ pub fn discover_root_ca_instance_from_tal_with_fetchers(
|
||||
rsync_fetcher: &dyn RsyncFetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
discover_root_ca_instance_from_tal_with_fetchers_impl(
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
tal,
|
||||
tal_url,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal_with_fetchers_strict_name(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
rsync_fetcher: &dyn RsyncFetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
discover_root_ca_instance_from_tal_with_fetchers_impl(
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
tal,
|
||||
tal_url,
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
fn discover_root_ca_instance_from_tal_with_fetchers_impl(
|
||||
http_fetcher: &dyn Fetcher,
|
||||
rsync_fetcher: &dyn RsyncFetcher,
|
||||
tal: Tal,
|
||||
tal_url: Option<String>,
|
||||
strict_name: bool,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
if tal.ta_uris.is_empty() {
|
||||
return Err(FromTalError::NoTaUris);
|
||||
@@ -127,13 +191,14 @@ pub fn discover_root_ca_instance_from_tal_with_fetchers(
|
||||
}
|
||||
};
|
||||
|
||||
let trust_anchor = match TrustAnchor::bind_der(tal.clone(), &ta_der, Some(ta_uri)) {
|
||||
Ok(ta) => ta,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("bind {ta_uri} failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let trust_anchor =
|
||||
match bind_trust_anchor_der(tal.clone(), &ta_der, Some(ta_uri), strict_name) {
|
||||
Ok(ta) => ta,
|
||||
Err(e) => {
|
||||
last_err = Some(format!("bind {ta_uri} failed: {e}"));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let ca_instance =
|
||||
match ca_instance_uris_from_ca_certificate(&trust_anchor.ta_certificate.rc_ca) {
|
||||
@@ -168,6 +233,19 @@ fn fetch_ta_der(
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_trust_anchor_der(
|
||||
tal: Tal,
|
||||
ta_der: &[u8],
|
||||
resolved_uri: Option<&Url>,
|
||||
strict_name: bool,
|
||||
) -> Result<TrustAnchor, TrustAnchorError> {
|
||||
if strict_name {
|
||||
TrustAnchor::bind_der_with_strict_name(tal, ta_der, resolved_uri)
|
||||
} else {
|
||||
TrustAnchor::bind_der(tal, ta_der, resolved_uri)
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_ta_der_via_rsync(
|
||||
rsync_fetcher: &dyn RsyncFetcher,
|
||||
ta_rsync_uri: &str,
|
||||
@@ -213,9 +291,26 @@ pub fn discover_root_ca_instance_from_tal_and_ta_der(
|
||||
tal_bytes: &[u8],
|
||||
ta_der: &[u8],
|
||||
resolved_ta_uri: Option<&Url>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
discover_root_ca_instance_from_tal_and_ta_der_impl(tal_bytes, ta_der, resolved_ta_uri, false)
|
||||
}
|
||||
|
||||
pub fn discover_root_ca_instance_from_tal_and_ta_der_with_strict_name(
|
||||
tal_bytes: &[u8],
|
||||
ta_der: &[u8],
|
||||
resolved_ta_uri: Option<&Url>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
discover_root_ca_instance_from_tal_and_ta_der_impl(tal_bytes, ta_der, resolved_ta_uri, true)
|
||||
}
|
||||
|
||||
fn discover_root_ca_instance_from_tal_and_ta_der_impl(
|
||||
tal_bytes: &[u8],
|
||||
ta_der: &[u8],
|
||||
resolved_ta_uri: Option<&Url>,
|
||||
strict_name: bool,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
let tal = Tal::decode_bytes(tal_bytes)?;
|
||||
let trust_anchor = TrustAnchor::bind_der(tal, ta_der, resolved_ta_uri)?;
|
||||
let trust_anchor = bind_trust_anchor_der(tal, ta_der, resolved_ta_uri, strict_name)?;
|
||||
let ca_instance = ca_instance_uris_from_ca_certificate(&trust_anchor.ta_certificate.rc_ca)?;
|
||||
Ok(DiscoveredRootCaInstance {
|
||||
tal_url: None,
|
||||
|
||||
@@ -28,6 +28,17 @@ 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 decode_resource_certificate_with_policy(
|
||||
der: &[u8],
|
||||
policy: &Policy,
|
||||
) -> Result<ResourceCertificate, crate::data_model::rc::ResourceCertificateDecodeError> {
|
||||
if policy.strict.name {
|
||||
ResourceCertificate::decode_der_with_strict_name(der)
|
||||
} else {
|
||||
ResourceCertificate::decode_der(der)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct VerifiedIssuerCrl {
|
||||
crl: crate::data_model::crl::RpkixCrl,
|
||||
@@ -178,11 +189,15 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
let mut audit: Vec<ObjectAuditEntry> = Vec::new();
|
||||
|
||||
// Enforce that `manifest_bytes` is actually a manifest object.
|
||||
let _manifest = ManifestObject::decode_der(manifest_bytes)
|
||||
.expect("publication point snapshot manifest decodes");
|
||||
let _manifest = ManifestObject::decode_der_with_strict_options(
|
||||
manifest_bytes,
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
)
|
||||
.expect("publication point snapshot manifest decodes");
|
||||
|
||||
// Decode issuer CA once; if it fails we cannot validate ROA/ASPA EE certificates.
|
||||
let issuer_ca = match ResourceCertificate::decode_der(issuer_ca_der) {
|
||||
let issuer_ca = match decode_resource_certificate_with_policy(issuer_ca_der, policy) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
stats.publication_point_dropped = true;
|
||||
@@ -349,6 +364,8 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
validation_time,
|
||||
timing,
|
||||
collect_vcir_local_outputs,
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
);
|
||||
match result.outcome {
|
||||
Ok(mut ok) => {
|
||||
@@ -457,6 +474,8 @@ pub fn process_publication_point_for_issuer_with_options<P: PublicationPointData
|
||||
validation_time,
|
||||
timing,
|
||||
collect_vcir_local_outputs,
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
) {
|
||||
Ok((att, local_output)) => {
|
||||
stats.aspa_ok += 1;
|
||||
@@ -739,6 +758,8 @@ pub(crate) struct OwnedRoaTask {
|
||||
issuer_effective_as: Option<crate::data_model::rc::AsResourceSet>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
pub(crate) submitted_at: Option<Instant>,
|
||||
}
|
||||
|
||||
@@ -844,6 +865,8 @@ fn validate_owned_roa_task(worker_index: usize, task: OwnedRoaTask) -> RoaTaskRe
|
||||
task.validation_time,
|
||||
None,
|
||||
task.collect_vcir_local_outputs,
|
||||
task.strict_cms_der,
|
||||
task.strict_name,
|
||||
)
|
||||
.map(|(vrps, local_outputs)| RoaTaskOk {
|
||||
vrps,
|
||||
@@ -881,6 +904,8 @@ pub(crate) struct ParallelObjectsStage {
|
||||
issuer_effective_as: Option<crate::data_model::rc::AsResourceSet>,
|
||||
validation_time: time::OffsetDateTime,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
warnings: Vec<Warning>,
|
||||
stats: ObjectsStats,
|
||||
audit: Vec<ObjectAuditEntry>,
|
||||
@@ -907,6 +932,8 @@ impl ParallelObjectsStage {
|
||||
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()
|
||||
@@ -928,6 +955,7 @@ impl ParallelObjectsStage {
|
||||
pub(crate) fn prepare_publication_point_for_parallel_roa<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>,
|
||||
@@ -950,10 +978,14 @@ pub(crate) fn prepare_publication_point_for_parallel_roa<P: PublicationPointData
|
||||
.count();
|
||||
let mut audit: Vec<ObjectAuditEntry> = Vec::new();
|
||||
|
||||
let _manifest = ManifestObject::decode_der(manifest_bytes)
|
||||
.expect("publication point snapshot manifest decodes");
|
||||
let _manifest = ManifestObject::decode_der_with_strict_options(
|
||||
manifest_bytes,
|
||||
policy.strict.cms_der,
|
||||
policy.strict.name,
|
||||
)
|
||||
.expect("publication point snapshot manifest decodes");
|
||||
|
||||
let issuer_ca = match ResourceCertificate::decode_der(issuer_ca_der) {
|
||||
let issuer_ca = match decode_resource_certificate_with_policy(issuer_ca_der, policy) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
stats.publication_point_dropped = true;
|
||||
@@ -1109,6 +1141,8 @@ pub(crate) fn prepare_publication_point_for_parallel_roa<P: PublicationPointData
|
||||
issuer_effective_as: issuer_effective_as.cloned(),
|
||||
validation_time,
|
||||
collect_vcir_local_outputs,
|
||||
strict_cms_der: policy.strict.cms_der,
|
||||
strict_name: policy.strict.name,
|
||||
warnings,
|
||||
stats,
|
||||
audit,
|
||||
@@ -1193,6 +1227,8 @@ pub(crate) fn reduce_parallel_roa_stage(
|
||||
stage.validation_time,
|
||||
timing,
|
||||
stage.collect_vcir_local_outputs,
|
||||
stage.strict_cms_der,
|
||||
stage.strict_name,
|
||||
) {
|
||||
Ok((att, local_output)) => {
|
||||
stats.aspa_ok += 1;
|
||||
@@ -1254,6 +1290,7 @@ fn process_publication_point_for_issuer_parallel_roa_inner<P: PublicationPointDa
|
||||
let stage = match prepare_publication_point_for_parallel_roa(
|
||||
0,
|
||||
publication_point,
|
||||
_policy,
|
||||
issuer_ca_der,
|
||||
issuer_ca_rsync_uri,
|
||||
issuer_effective_ip,
|
||||
@@ -1411,6 +1448,8 @@ pub(crate) fn validate_roa_task_serial(
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
) -> RoaTaskResult {
|
||||
let sha256_hex = sha256_hex_from_32(&task.file.sha256);
|
||||
let outcome = process_roa_with_issuer(
|
||||
@@ -1427,6 +1466,8 @@ pub(crate) fn validate_roa_task_serial(
|
||||
validation_time,
|
||||
timing,
|
||||
collect_vcir_local_outputs,
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
)
|
||||
.map(|(vrps, local_outputs)| RoaTaskOk {
|
||||
vrps,
|
||||
@@ -1459,11 +1500,17 @@ fn process_roa_with_issuer(
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
) -> Result<(Vec<Vrp>, Vec<VcirLocalOutput>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_roa_decode_and_validate_total"));
|
||||
let roa = RoaObject::decode_der(file.bytes().map_err(ObjectValidateError::BytesLoad)?)?;
|
||||
let roa = RoaObject::decode_der_with_strict_options(
|
||||
file.bytes().map_err(ObjectValidateError::BytesLoad)?,
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
)?;
|
||||
drop(_decode);
|
||||
|
||||
let _ee_profile = timing
|
||||
@@ -1575,11 +1622,17 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
) -> Result<(Vec<Vrp>, Vec<VcirLocalOutput>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_roa_decode_and_validate_total"));
|
||||
let roa = RoaObject::decode_der(file.bytes().map_err(ObjectValidateError::BytesLoad)?)?;
|
||||
let roa = RoaObject::decode_der_with_strict_options(
|
||||
file.bytes().map_err(ObjectValidateError::BytesLoad)?,
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
)?;
|
||||
drop(_decode);
|
||||
|
||||
let _ee_profile = timing
|
||||
@@ -1697,11 +1750,17 @@ fn process_aspa_with_issuer(
|
||||
validation_time: time::OffsetDateTime,
|
||||
timing: Option<&TimingHandle>,
|
||||
collect_vcir_local_outputs: bool,
|
||||
strict_cms_der: bool,
|
||||
strict_name: bool,
|
||||
) -> Result<(AspaAttestation, Option<VcirLocalOutput>), ObjectValidateError> {
|
||||
let _decode = timing
|
||||
.as_ref()
|
||||
.map(|t| t.span_phase("objects_aspa_decode_and_validate_total"));
|
||||
let aspa = AspaObject::decode_der(file.bytes().map_err(ObjectValidateError::BytesLoad)?)?;
|
||||
let aspa = AspaObject::decode_der_with_strict_options(
|
||||
file.bytes().map_err(ObjectValidateError::BytesLoad)?,
|
||||
strict_cms_der,
|
||||
strict_name,
|
||||
)?;
|
||||
drop(_decode);
|
||||
|
||||
let _ee_profile = timing
|
||||
|
||||
@@ -24,7 +24,11 @@ use crate::replay::fetch_rsync::PayloadReplayRsyncFetcher;
|
||||
use crate::sync::rrdp::Fetcher;
|
||||
use crate::validation::from_tal::{
|
||||
DiscoveredRootCaInstance, FromTalError, discover_root_ca_instance_from_tal_and_ta_der,
|
||||
discover_root_ca_instance_from_tal_url, discover_root_ca_instance_from_tal_with_fetchers,
|
||||
discover_root_ca_instance_from_tal_and_ta_der_with_strict_name,
|
||||
discover_root_ca_instance_from_tal_url,
|
||||
discover_root_ca_instance_from_tal_url_with_strict_name,
|
||||
discover_root_ca_instance_from_tal_with_fetchers,
|
||||
discover_root_ca_instance_from_tal_with_fetchers_strict_name,
|
||||
};
|
||||
use crate::validation::objects::ParallelRoaWorkerPool;
|
||||
use crate::validation::tree::{
|
||||
@@ -86,6 +90,7 @@ pub struct RunTreeFromTalOutput {
|
||||
pub struct RunTreeFromTalAuditOutput {
|
||||
pub discovery: DiscoveredRootCaInstance,
|
||||
pub discoveries: Vec<DiscoveredRootCaInstance>,
|
||||
pub successful_tal_inputs: Vec<TalInputSpec>,
|
||||
pub tree: TreeRunOutput,
|
||||
pub publication_points: Vec<PublicationPointAudit>,
|
||||
pub downloads: Vec<crate::audit::AuditDownloadEvent>,
|
||||
@@ -196,19 +201,48 @@ fn root_discovery_from_tal_input(
|
||||
tal_input: &TalInputSpec,
|
||||
http_fetcher: &dyn Fetcher,
|
||||
rsync_fetcher: &dyn crate::fetch::rsync::RsyncFetcher,
|
||||
strict_name: bool,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
match &tal_input.source {
|
||||
TalSource::Url(url) => discover_root_ca_instance_from_tal_url(http_fetcher, url),
|
||||
TalSource::Url(url) => {
|
||||
if strict_name {
|
||||
discover_root_ca_instance_from_tal_url_with_strict_name(http_fetcher, url)
|
||||
} else {
|
||||
discover_root_ca_instance_from_tal_url(http_fetcher, url)
|
||||
}
|
||||
}
|
||||
TalSource::DerBytes {
|
||||
tal_bytes, ta_der, ..
|
||||
} => discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, None),
|
||||
} => {
|
||||
if strict_name {
|
||||
discover_root_ca_instance_from_tal_and_ta_der_with_strict_name(
|
||||
tal_bytes, ta_der, None,
|
||||
)
|
||||
} else {
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, None)
|
||||
}
|
||||
}
|
||||
TalSource::FilePath(path) => {
|
||||
let tal_bytes = std::fs::read(path).map_err(|e| {
|
||||
FromTalError::TalFetch(format!("read TAL file failed: {}: {e}", path.display()))
|
||||
})?;
|
||||
let tal = crate::data_model::tal::Tal::decode_bytes(&tal_bytes)
|
||||
.map_err(FromTalError::from)?;
|
||||
discover_root_ca_instance_from_tal_with_fetchers(http_fetcher, rsync_fetcher, tal, None)
|
||||
if strict_name {
|
||||
discover_root_ca_instance_from_tal_with_fetchers_strict_name(
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
tal,
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
discover_root_ca_instance_from_tal_with_fetchers(
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
tal,
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
TalSource::FilePathWithTa { tal_path, ta_path } => {
|
||||
let tal_bytes = std::fs::read(tal_path).map_err(|e| {
|
||||
@@ -217,19 +251,76 @@ fn root_discovery_from_tal_input(
|
||||
let ta_der = std::fs::read(ta_path).map_err(|e| {
|
||||
FromTalError::TaFetch(format!("read TA file failed: {}: {e}", ta_path.display()))
|
||||
})?;
|
||||
discover_root_ca_instance_from_tal_and_ta_der(&tal_bytes, &ta_der, None)
|
||||
if strict_name {
|
||||
discover_root_ca_instance_from_tal_and_ta_der_with_strict_name(
|
||||
&tal_bytes, &ta_der, None,
|
||||
)
|
||||
} else {
|
||||
discover_root_ca_instance_from_tal_and_ta_der(&tal_bytes, &ta_der, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn discover_root_ca_instance_from_tal_url_with_policy(
|
||||
policy: &crate::policy::Policy,
|
||||
http_fetcher: &dyn Fetcher,
|
||||
tal_url: &str,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
if policy.strict.name {
|
||||
discover_root_ca_instance_from_tal_url_with_strict_name(http_fetcher, tal_url)
|
||||
} else {
|
||||
discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)
|
||||
}
|
||||
}
|
||||
|
||||
fn discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy: &crate::policy::Policy,
|
||||
tal_bytes: &[u8],
|
||||
ta_der: &[u8],
|
||||
resolved_ta_uri: Option<&Url>,
|
||||
) -> Result<DiscoveredRootCaInstance, FromTalError> {
|
||||
if policy.strict.name {
|
||||
discover_root_ca_instance_from_tal_and_ta_der_with_strict_name(
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)
|
||||
} else {
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)
|
||||
}
|
||||
}
|
||||
|
||||
fn discover_multiple_roots_from_tal_inputs(
|
||||
tal_inputs: &[TalInputSpec],
|
||||
http_fetcher: &dyn Fetcher,
|
||||
rsync_fetcher: &dyn crate::fetch::rsync::RsyncFetcher,
|
||||
strict_name: bool,
|
||||
) -> Result<Vec<TalRootDiscovery>, RunTreeFromTalError> {
|
||||
let mut roots = Vec::with_capacity(tal_inputs.len());
|
||||
for tal_input in tal_inputs {
|
||||
let discovery = root_discovery_from_tal_input(tal_input, http_fetcher, rsync_fetcher)?;
|
||||
let discovery = match root_discovery_from_tal_input(
|
||||
tal_input,
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
strict_name,
|
||||
) {
|
||||
Ok(discovery) => discovery,
|
||||
Err(error)
|
||||
if should_isolate_multi_tal_strict_name_failure(
|
||||
tal_inputs.len(),
|
||||
strict_name,
|
||||
&error,
|
||||
) =>
|
||||
{
|
||||
eprintln!(
|
||||
"warning: skipping TAL '{}' because strict name validation failed during trust anchor discovery: {error}",
|
||||
tal_input.tal_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
Err(error) => return Err(error.into()),
|
||||
};
|
||||
let root_handle = root_handle_from_trust_anchor(
|
||||
&discovery.trust_anchor,
|
||||
tal_input.tal_id.clone(),
|
||||
@@ -242,9 +333,25 @@ fn discover_multiple_roots_from_tal_inputs(
|
||||
root_handle,
|
||||
});
|
||||
}
|
||||
if roots.is_empty() {
|
||||
return Err(RunTreeFromTalError::Replay(
|
||||
"multi-TAL root discovery returned no usable roots after strict name filtering"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
Ok(roots)
|
||||
}
|
||||
|
||||
fn should_isolate_multi_tal_strict_name_failure(
|
||||
tal_input_count: usize,
|
||||
strict_name: bool,
|
||||
error: &FromTalError,
|
||||
) -> bool {
|
||||
strict_name
|
||||
&& tal_input_count > 1
|
||||
&& error.to_string().contains("Name strict validation failed")
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum RunTreeFromTalError {
|
||||
#[error("{0}")]
|
||||
@@ -288,7 +395,8 @@ pub fn run_tree_from_tal_url_serial(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalOutput, RunTreeFromTalError> {
|
||||
let discovery = discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)?;
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_url_with_policy(policy, http_fetcher, tal_url)?;
|
||||
|
||||
let runner = make_live_runner(
|
||||
store,
|
||||
@@ -325,7 +433,8 @@ pub fn run_tree_from_tal_url_serial_audit(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let discovery = discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)?;
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_url_with_policy(policy, http_fetcher, tal_url)?;
|
||||
|
||||
let download_log = DownloadLogHandle::new();
|
||||
let runner = make_live_runner(
|
||||
@@ -359,6 +468,7 @@ pub fn run_tree_from_tal_url_serial_audit(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -379,7 +489,8 @@ pub fn run_tree_from_tal_url_serial_audit_with_timing(
|
||||
timing: &TimingHandle,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let _tal = timing.span_phase("tal_bootstrap");
|
||||
let discovery = discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)?;
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_url_with_policy(policy, http_fetcher, tal_url)?;
|
||||
drop(_tal);
|
||||
|
||||
let download_log = DownloadLogHandle::new();
|
||||
@@ -415,6 +526,7 @@ pub fn run_tree_from_tal_url_serial_audit_with_timing(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -489,6 +601,7 @@ where
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -523,7 +636,12 @@ where
|
||||
"multi-TAL run requires at least one TAL input".to_string(),
|
||||
));
|
||||
}
|
||||
let roots = discover_multiple_roots_from_tal_inputs(&tal_inputs, http_fetcher, rsync_fetcher)?;
|
||||
let roots = discover_multiple_roots_from_tal_inputs(
|
||||
&tal_inputs,
|
||||
http_fetcher,
|
||||
rsync_fetcher,
|
||||
policy.strict.name,
|
||||
)?;
|
||||
let primary = roots.first().cloned().ok_or_else(|| {
|
||||
RunTreeFromTalError::Replay("multi-TAL root discovery returned no roots".to_string())
|
||||
})?;
|
||||
@@ -531,9 +649,13 @@ where
|
||||
.iter()
|
||||
.map(|item| item.discovery.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let successful_tal_inputs = roots
|
||||
.iter()
|
||||
.map(|item| item.tal_input.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let root_handles = roots
|
||||
.into_iter()
|
||||
.map(|item| item.root_handle)
|
||||
.iter()
|
||||
.map(|item| item.root_handle.clone())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let download_log = DownloadLogHandle::new();
|
||||
@@ -545,7 +667,7 @@ where
|
||||
parallel_config,
|
||||
None,
|
||||
Some(download_log.clone()),
|
||||
tal_inputs,
|
||||
successful_tal_inputs.clone(),
|
||||
)?;
|
||||
let current_repo_index_for_output = current_repo_index.clone();
|
||||
let runner = make_live_runner(
|
||||
@@ -583,6 +705,7 @@ where
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: primary.discovery.clone(),
|
||||
discoveries,
|
||||
successful_tal_inputs,
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -610,7 +733,8 @@ where
|
||||
H: Fetcher + Clone + 'static,
|
||||
R: crate::fetch::rsync::RsyncFetcher + Clone + 'static,
|
||||
{
|
||||
let discovery = discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)?;
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_url_with_policy(policy, http_fetcher, tal_url)?;
|
||||
run_single_root_parallel_audit_inner(
|
||||
store,
|
||||
policy,
|
||||
@@ -643,8 +767,12 @@ where
|
||||
H: Fetcher + Clone + 'static,
|
||||
R: crate::fetch::rsync::RsyncFetcher + Clone + 'static,
|
||||
{
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
let derived_tal_id = derive_tal_id(&discovery);
|
||||
let tal_inputs = vec![TalInputSpec {
|
||||
tal_id: derived_tal_id.clone(),
|
||||
@@ -718,7 +846,8 @@ where
|
||||
H: Fetcher + Clone + 'static,
|
||||
R: crate::fetch::rsync::RsyncFetcher + Clone + 'static,
|
||||
{
|
||||
let discovery = discover_root_ca_instance_from_tal_url(http_fetcher, tal_url)?;
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_url_with_policy(policy, http_fetcher, tal_url)?;
|
||||
run_single_root_parallel_audit_inner(
|
||||
store,
|
||||
policy,
|
||||
@@ -752,8 +881,12 @@ where
|
||||
H: Fetcher + Clone + 'static,
|
||||
R: crate::fetch::rsync::RsyncFetcher + Clone + 'static,
|
||||
{
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
let derived_tal_id = derive_tal_id(&discovery);
|
||||
let tal_inputs = vec![TalInputSpec {
|
||||
tal_id: derived_tal_id.clone(),
|
||||
@@ -823,8 +956,12 @@ pub fn run_tree_from_tal_and_ta_der_serial(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalOutput, RunTreeFromTalError> {
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
|
||||
let runner = Rpkiv1PublicationPointRunner {
|
||||
store,
|
||||
@@ -916,6 +1053,7 @@ pub fn run_tree_from_tal_bytes_serial_audit(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -987,6 +1125,7 @@ pub fn run_tree_from_tal_bytes_serial_audit_with_timing(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1007,8 +1146,12 @@ pub fn run_tree_from_tal_and_ta_der_serial_audit(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
|
||||
let download_log = DownloadLogHandle::new();
|
||||
let runner = Rpkiv1PublicationPointRunner {
|
||||
@@ -1049,6 +1192,7 @@ pub fn run_tree_from_tal_and_ta_der_serial_audit(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1071,8 +1215,12 @@ pub fn run_tree_from_tal_and_ta_der_serial_audit_with_timing(
|
||||
timing: &TimingHandle,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let _tal = timing.span_phase("tal_bootstrap");
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
drop(_tal);
|
||||
|
||||
let download_log = DownloadLogHandle::new();
|
||||
@@ -1115,6 +1263,7 @@ pub fn run_tree_from_tal_and_ta_der_serial_audit_with_timing(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1135,8 +1284,12 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalOutput, RunTreeFromTalError> {
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
let replay_index = Arc::new(
|
||||
ReplayArchiveIndex::load_allow_missing_rsync_modules(
|
||||
payload_archive_root,
|
||||
@@ -1192,8 +1345,12 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
let replay_index = Arc::new(
|
||||
ReplayArchiveIndex::load_allow_missing_rsync_modules(
|
||||
payload_archive_root,
|
||||
@@ -1244,6 +1401,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1266,8 +1424,12 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit_with_timing(
|
||||
timing: &TimingHandle,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let _tal = timing.span_phase("tal_bootstrap");
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
drop(_tal);
|
||||
let replay_index = Arc::new(
|
||||
ReplayArchiveIndex::load_allow_missing_rsync_modules(
|
||||
@@ -1320,6 +1482,7 @@ pub fn run_tree_from_tal_and_ta_der_payload_replay_serial_audit_with_timing(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1536,6 +1699,7 @@ fn run_payload_delta_replay_audit_inner(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1559,8 +1723,12 @@ pub fn run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
run_payload_delta_replay_audit_inner(
|
||||
store,
|
||||
policy,
|
||||
@@ -1592,8 +1760,12 @@ pub fn run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit_with_timin
|
||||
timing: &TimingHandle,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let _tal = timing.span_phase("tal_bootstrap");
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
drop(_tal);
|
||||
run_payload_delta_replay_audit_inner(
|
||||
store,
|
||||
@@ -1681,6 +1853,7 @@ fn run_payload_delta_replay_step_audit_inner(
|
||||
Ok(RunTreeFromTalAuditOutput {
|
||||
discovery: discovery.clone(),
|
||||
discoveries: vec![discovery],
|
||||
successful_tal_inputs: Vec::new(),
|
||||
tree,
|
||||
publication_points,
|
||||
downloads,
|
||||
@@ -1702,8 +1875,12 @@ pub fn run_tree_from_tal_and_ta_der_payload_delta_replay_step_serial_audit(
|
||||
validation_time: time::OffsetDateTime,
|
||||
config: &TreeRunConfig,
|
||||
) -> Result<RunTreeFromTalAuditOutput, RunTreeFromTalError> {
|
||||
let discovery =
|
||||
discover_root_ca_instance_from_tal_and_ta_der(tal_bytes, ta_der, resolved_ta_uri)?;
|
||||
let discovery = discover_root_ca_instance_from_tal_and_ta_der_with_policy(
|
||||
policy,
|
||||
tal_bytes,
|
||||
ta_der,
|
||||
resolved_ta_uri,
|
||||
)?;
|
||||
run_payload_delta_replay_step_audit_inner(
|
||||
store,
|
||||
policy,
|
||||
@@ -1790,6 +1967,7 @@ mod multi_tal_tests {
|
||||
&tal_inputs,
|
||||
&RejectingHttpFetcher,
|
||||
&RejectingRsyncFetcher,
|
||||
false,
|
||||
)
|
||||
.expect("discover roots");
|
||||
|
||||
@@ -1803,6 +1981,54 @@ mod multi_tal_tests {
|
||||
roots[1].root_handle.manifest_rsync_uri
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discover_multiple_roots_isolates_strict_name_failure() {
|
||||
let apnic_tal =
|
||||
std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal").expect("read apnic tal");
|
||||
let apnic_ta = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta");
|
||||
let arin_tal = std::fs::read("tests/fixtures/tal/arin.tal").expect("read arin tal");
|
||||
let arin_ta = std::fs::read("tests/fixtures/ta/arin-ta.cer").expect("read arin ta");
|
||||
|
||||
let tal_inputs = vec![
|
||||
TalInputSpec::from_ta_der("https://example.test/apnic.tal", apnic_tal, apnic_ta),
|
||||
TalInputSpec::from_ta_der("https://example.test/arin.tal", arin_tal, arin_ta),
|
||||
];
|
||||
|
||||
let roots = discover_multiple_roots_from_tal_inputs(
|
||||
&tal_inputs,
|
||||
&RejectingHttpFetcher,
|
||||
&RejectingRsyncFetcher,
|
||||
true,
|
||||
)
|
||||
.expect("strict discovery should keep usable roots");
|
||||
|
||||
assert_eq!(roots.len(), 1);
|
||||
assert_eq!(roots[0].tal_input.tal_id, "arin");
|
||||
assert_eq!(roots[0].root_handle.tal_id, "arin");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn discover_single_root_keeps_strict_name_failure_fatal() {
|
||||
let apnic_tal =
|
||||
std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal").expect("read apnic tal");
|
||||
let apnic_ta = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta");
|
||||
let tal_inputs = vec![TalInputSpec::from_ta_der(
|
||||
"https://example.test/apnic.tal",
|
||||
apnic_tal,
|
||||
apnic_ta,
|
||||
)];
|
||||
|
||||
let error = discover_multiple_roots_from_tal_inputs(
|
||||
&tal_inputs,
|
||||
&RejectingHttpFetcher,
|
||||
&RejectingRsyncFetcher,
|
||||
true,
|
||||
)
|
||||
.expect_err("single-TAL strict failure should remain fatal");
|
||||
|
||||
assert!(error.to_string().contains("Name strict validation failed"));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -858,6 +858,7 @@ fn stage_ready_publication_point(
|
||||
match prepare_publication_point_for_parallel_roa(
|
||||
ready.node.id,
|
||||
&fresh_stage.fresh_point,
|
||||
runner.policy,
|
||||
&ready.node.handle.ca_certificate_der,
|
||||
ready.node.handle.ca_certificate_rsync_uri.as_deref(),
|
||||
ready.node.handle.effective_ip_resources.as_ref(),
|
||||
|
||||
Reference in New Issue
Block a user