Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider manifest cert for chain validity and note when points go stale. #945

Merged
merged 2 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions doc/manual/source/advanced-features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ in the :term:`json` and :term:`jsonext` output formats, e.g.:
},
"chainValidity": {
"notBefore": "2023-04-18T14:32:13Z",
"notAfter": "2024-07-01T00:00:00Z"
}
"notAfter": "2023-04-20T00:00:00Z"
},
"stale": "2023-04-20T00:00:00Z"
}]
}],
"routerKeys": [],
Expand All @@ -73,8 +74,9 @@ in the :term:`json` and :term:`jsonext` output formats, e.g.:
},
"chainValidity": {
"notBefore": "2023-04-18T14:32:13Z",
"notAfter": "2024-04-11T07:26:24Z"
}
"notAfter": "2023-04-20T00:00:00Z"
},
"stale": "2023-04-20T00:00:00Z"
}]
}]
}
Expand Down Expand Up @@ -125,8 +127,9 @@ in the :term:`SLURM`, :term:`json` and :term:`jsonext` output formats, e.g.:
},
"chainValidity": {
"notBefore": "2021-05-06T12:51:30Z",
"notAfter": "2022-07-01T00:00:00Z"
}
"notAfter": "2021-05-08T00:00:00Z"
},
"stale": "2021-05-08T00:00:00Z"
}]
}],
"routerKeys": [{
Expand All @@ -142,8 +145,9 @@ in the :term:`SLURM`, :term:`json` and :term:`jsonext` output formats, e.g.:
},
"chainValidity": {
"notBefore": "2022-01-16T14:45:51Z",
"notAfter": "2022-08-06T00:00:00Z"
}
"notAfter": "2021-01-18T00:00:00Z"
},
"stale": "2021-01-18T00:00:00Z"
}]
}],
"aspas": []
Expand Down Expand Up @@ -205,4 +209,4 @@ Routinator will report the resources used to sign the object:
- `A proof-of-concept for constructing and validating RTAs
<https://github.com/APNIC-net/rpki-rta-demo>`_

.. versionadded:: 0.8.0
.. versionadded:: 0.8.0
6 changes: 4 additions & 2 deletions doc/manual/source/manual-page.rst
Original file line number Diff line number Diff line change
Expand Up @@ -542,9 +542,11 @@ These can be requested by providing different commands on the command line.
For RPKI objects, *tal* provides the name of the trust
anchor locator the object was published under, *uri*
provides the rsync URI of the ROA or router certificate,
*validity* provides the validity of the ROA itself, and
*validity* provides the validity of the ROA itself,
*chainValidity* the validity considering the validity of
the certificates along the validation chain.
the certificates along the validation chain, and
*stale* the time when any of the publication points along
the validation chain becomes stale.

For assertions from local exceptions, *path* will provide
the path of the local exceptions file and, optionally,
Expand Down
20 changes: 12 additions & 8 deletions doc/manual/source/output-formats.rst
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,10 @@ generated in a wide range of output formats for various use cases.
For RPKI objects, *tal* provides the name of the trust anchor
locator the object was published under, *uri* provides the rsync
URI of the ROA or router certificate, *validity* provides the
validity of the ROA itself, and *chainValidity* the validity
validity of the ROA itself, *chainValidity* the validity
considering the validity of the certificates along the validation
chain.
chain, and *stale* the time when any of the publication points along
the validation chain becomes stale.

For assertions from local exceptions, *path* will provide the path
of the local exceptions file and, optionally, *comment* will
Expand Down Expand Up @@ -244,8 +245,9 @@ generated in a wide range of output formats for various use cases.
},
"chainValidity": {
"notBefore": "2022-07-25T20:47:37Z",
"notAfter": "2023-02-24T12:31:01Z"
}
"notAfter": "2022-07-26T00:00:00Z"
},
"stale": "2022-07-26T00:00:00Z"
}]
}
],
Expand All @@ -263,8 +265,9 @@ generated in a wide range of output formats for various use cases.
},
"chainValidity": {
"notBefore": "2022-07-25T20:47:37Z",
"notAfter": "2023-02-24T12:31:01Z"
}
"notAfter": "2022-07-26T00:00:00Z"
},
"stale": "2022-07-26T00:00:00Z"
}]
}],
"aspas": [{
Expand All @@ -281,8 +284,9 @@ generated in a wide range of output formats for various use cases.
},
"chainValidity": {
"notBefore": "2023-04-18T14:32:13Z",
"notAfter": "2024-04-11T07:26:24Z"
}
"notAfter": "2023-04-20T00:00:00Z"
},
"stale": "2022-07-26T00:00:00Z"
}]
}]
}
Expand Down
62 changes: 37 additions & 25 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/// the accompanying trait [`ProcessPubPoint`] dealing with individual
/// publication points.

use std::{fmt, fs, thread};
use std::{cmp, fmt, fs, thread};
use std::borrow::Cow;
use std::collections::HashMap;
use std::fs::File;
Expand Down Expand Up @@ -705,15 +705,20 @@ impl<'a, P: ProcessRun> PubPoint<'a, P> {
}
};

// The manifest is fine, so we can now look at the objects. The
// The manifest is fine, so we can continue.
//
// First, report its validity to the processor.
collected.point_validity(&mut self.processor);

// We can look at the objects now. The
// objects are fine if they are present and match the hash. If they
// don’t we have to cancel the update. We also validate them while we
// are at it. This also collects all the child CAs that need
// processing later on in `ca_tasks`.
//
// However, the processor can decide it doesn’t like the publication
// point at all. This is not an error -- the publication point is
// correct from a store perspective --, but we must not process te
// correct from a store perspective --, but we must not process the
// collected `ca_tasks`. We keep track of this through `point_ok` and,
// if that happens to end up being `false` return an empty list to
// signal that the publication point was processed successfully but
Expand Down Expand Up @@ -1029,6 +1034,8 @@ impl<'a, P: ProcessRun> PubPoint<'a, P> {
}
};

manifest.point_validity(&mut self.processor);

let mut ca_tasks = Vec::new();
for object in &mut store {
let object = match object {
Expand Down Expand Up @@ -1332,13 +1339,12 @@ impl<'a, P: ProcessRun> PubPoint<'a, P> {

manifest.metrics.valid_ca_certs += 1;

let mut processor = match self.processor.process_ca(
let processor = match self.processor.process_ca(
uri, &cert
)? {
Some(processor) => processor,
None => return Ok(())
};
processor.update_refresh(cert.cert().validity().not_after());

// Defer operation if we need to update the repository part where
// the CA lives.
Expand Down Expand Up @@ -1543,6 +1549,17 @@ impl ValidPointManifest {

Ok(())
}

/// Reports the validity to the given processor.
fn point_validity(&self, processor: &mut impl ProcessPubPoint) {
processor.point_validity(
self.ee_cert.validity(),
cmp::min(
self.content.next_update(),
self.crl.next_update(),
)
)
}
}


Expand Down Expand Up @@ -1610,6 +1627,9 @@ struct CaTask<P> {
//------------ CaCert --------------------------------------------------------

/// A CA certificate plus references to all its parents.
///
/// Note that this does not represent the full publication point, only the
/// certificate itself.
#[derive(Clone, Debug)]
pub struct CaCert {
/// The CA certificate of this CA.
Expand Down Expand Up @@ -1640,12 +1660,6 @@ pub struct CaCert {
/// The index of the TAL in the metrics.
pub(crate) // XXX
tal: usize,

/// The combined validity of the certificate.
///
/// This is derived from the validity of all the parents and the
/// certificate itself.
combined_validity: Validity,
}

impl CaCert {
Expand Down Expand Up @@ -1695,10 +1709,6 @@ impl CaCert {
chain_len: usize,
tal: usize,
) -> Result<Arc<Self>, Failed> {
let combined_validity = match parent.as_ref() {
Some(ca) => cert.validity().trim(ca.combined_validity()),
None => cert.validity()
};
let ca_repository = match cert.ca_repository() {
Some(uri) => uri.clone(),
None => {
Expand Down Expand Up @@ -1727,8 +1737,7 @@ impl CaCert {
}
};
Ok(Arc::new(CaCert {
cert, uri, ca_repository, rpki_manifest, parent, chain_len, tal,
combined_validity,
cert, uri, ca_repository, rpki_manifest, parent, chain_len, tal
}))
}

Expand Down Expand Up @@ -1783,11 +1792,6 @@ impl CaCert {
self.cert.rpki_notify()
}

/// Returns the combined validaty of the whole CA.
pub fn combined_validity(&self) -> Validity {
self.combined_validity
}

/// Returns whether the CA is in a different repository from its parent.
///
/// This is just a quick check and may report a switch when in fact there
Expand Down Expand Up @@ -1947,9 +1951,17 @@ pub trait ProcessPubPoint: Sized + Send + Sync {
let _ = repository_index;
}

/// Updates the refresh time for this publication poont.
fn update_refresh(&mut self, not_after: Time) {
let _ = not_after;
/// Process the publication points’s validity.
///
/// The validity of the manifest’s EE certificate is provided in
/// `manifest_ee`. The smaller of the manifest’s and CRL’s next update
/// time is given in `stale`.
fn point_validity(
&mut self,
manifest_ee: Validity,
stale: Time,
) {
let _ = (manifest_ee, stale);
}

/// Determines whether an object with the given URI should be processed.
Expand Down
4 changes: 3 additions & 1 deletion src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,13 +1020,15 @@ impl ExtendedJson {
\"validity\": {{ \"notBefore\": \"{}\", \
\"notAfter\": \"{}\" }}, \
\"chainValidity\": {{ \"notBefore\": \"{}\", \
\"notAfter\": \"{}\" }} \
\"notAfter\": \"{}\" }}, \
\"stale\": \"{}\" \
}}",
json_str(roa.tal.name()),
format_iso_date(roa.roa_validity.not_before().into()),
format_iso_date(roa.roa_validity.not_after().into()),
format_iso_date(roa.chain_validity.not_before().into()),
format_iso_date(roa.chain_validity.not_after().into()),
format_iso_date(roa.point_stale.into()),
)?;
}
if let Some(exc) = item.exception_info() {
Expand Down
24 changes: 18 additions & 6 deletions src/payload/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use std::sync::Arc;
use rpki::uri;
use rpki::repository::cert::{Cert, ResourceCert};
use rpki::repository::tal::TalInfo;
use rpki::repository::x509::Validity;
use crate::engine::CaCert;
use rpki::repository::x509::{Validity, Time};
use crate::slurm::ExceptionInfo;

//------------ PayloadInfo ---------------------------------------------------
Expand Down Expand Up @@ -144,29 +143,42 @@ pub struct PublishInfo {

/// The validity of the validation chain.
pub chain_validity: Validity,

/// When will the object’s publication point become stale?
pub point_stale: Time,
}

impl PublishInfo {
/// Creates a new origin info from the EE certificate of a ROA.
pub fn signed_object(cert: &ResourceCert, ca_validity: Validity) -> Self {
pub fn signed_object(
cert: &ResourceCert,
ca_validity: Validity,
point_stale: Time,
) -> Self {
PublishInfo {
tal: cert.tal().clone(),
uri: cert.signed_object().cloned().map(|mut uri| {
uri.unshare(); uri
}),
roa_validity: cert.validity(),
chain_validity: cert.validity().trim(ca_validity),
point_stale,
}
}

pub fn router_cert(
cert: &Cert, uri: &uri::Rsync, ca_cert: &CaCert
cert: &Cert,
uri: &uri::Rsync,
tal: Arc<TalInfo>,
ca_validity: Validity,
point_stale: Time,
) -> Self {
PublishInfo {
tal: ca_cert.cert().tal().clone(),
tal,
uri: Some(uri.clone()),
roa_validity: cert.validity(),
chain_validity: cert.validity().trim(ca_cert.combined_validity())
chain_validity: cert.validity().trim(ca_validity),
point_stale,
}
}

Expand Down
Loading
Loading