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

Allow for reinitialising of the TA cert #1250

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
31 changes: 27 additions & 4 deletions doc/manual/source/trust-anchor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,10 @@ endpoints for the TA certificate.

.. code-block:: bash

krillta signer init --proxy_id ./proxy-id.json \
--proxy_repository_contact ./proxy-repo.json \
--tal_https <HTTPS URI for TA cert on TAL> \
--tal_rsync <RSYNC URI for TA cert on TAL>
krillta signer init --proxy-id ./proxy-id.json \
--proxy-repository-contact ./proxy-repo.json \
--tal-https <HTTPS URI for TA cert on TAL> \
--tal-rsync <RSYNC URI for TA cert on TAL>


Associate the TA Signer with the Proxy
Expand Down Expand Up @@ -468,3 +468,26 @@ friendlier to the human eye:
.. code-block:: bash

krillta signer exchanges --format text


Changing the TA certificate
---------------------------

There may be a reason why you want to change the TA certificate without
starting from scratch. Reasons might include: changes in the timing config,
the TA certificate expiring, and changes in the HTTPS or rsync URI.

In order to recreate the TA certificate, run the following command with the
new parameters:

.. code-block:: bash

krillta signer reinit

Be aware that the private key also has to be supplied as an argument. After
that, the flow is the same as for the initial initialisation:

.. code-block:: bash
krillta signer show > ./signer-info.json
krillta proxy signer init --info ./signer-info.json

57 changes: 57 additions & 0 deletions src/cli/ta/options/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ pub enum Subcommand {
/// Initialise the signer
Init(Init),

/// Reinitialise an already initialised signer
Reinit(Reinit),

/// Show the signer info
Show(Show),

Expand All @@ -73,6 +76,7 @@ impl Subcommand {
pub fn run(self, manager: &TrustAnchorSignerManager) -> Report {
match self {
Self::Init(cmd) => cmd.run(manager).into(),
Self::Reinit(cmd) => cmd.run(manager).into(),
Self::Show(cmd) => cmd.run(manager).into(),
Self::Process(cmd) => cmd.run(manager).into(),
Self::Last(cmd) => cmd.run(manager).into(),
Expand Down Expand Up @@ -109,6 +113,10 @@ pub struct Init {
/// Set the initial manifest number
#[arg(long, value_name = "number", default_value = "1")]
initial_manifest_number: u64,

/// Force the signer to reinitialise even if previously already initialised
#[arg(long, action)]
force: bool
}

impl Init {
Expand All @@ -123,6 +131,55 @@ impl Init {
tal_rsync: self.tal_rsync,
private_key_pem: self.private_key_pem.map(|x| x.0),
ta_mft_nr_override: Some(self.initial_manifest_number),
force: self.force
}
)
}
}


//------------ Reinit ----------------------------------------------------------

#[derive(clap::Args)]
pub struct Reinit {
/// Path to the proxy ID JSON file.
#[arg(long, short = 'i', value_name = "path")]
proxy_id: JsonFile<api::IdCertInfo, IdiMsg>,

/// Path to the proxy repository contact JSON file.
#[arg(long, short = 'r', value_name = "path")]
proxy_repository_contact: JsonFile<api::RepositoryContact, RcMsg>,

/// The rsync URI used for TA certificate on TAL and AIA
#[arg(long, value_name = "rsync URI")]
tal_rsync: uri::Rsync,

/// The HTTPS URI used for the TAL.
#[arg(long, value_name = "HTTPS URI")]
tal_https: Vec<uri::Https>,

/// The private key for the already initialised signer in PEM format
#[arg(long, value_name = "path")]
private_key_pem: PrivateKeyFile,

/// Set the manifest number
#[arg(long, value_name = "number", default_value = "1")]
initial_manifest_number: u64,
}

impl Reinit {
pub fn run(
self, manager: &TrustAnchorSignerManager
) -> Result<api::Success, SignerClientError> {
manager.init(
SignerInitInfo {
proxy_id: self.proxy_id.content,
repo_info: self.proxy_repository_contact.content.into(),
tal_https: self.tal_https,
tal_rsync: self.tal_rsync,
private_key_pem: Some(self.private_key_pem.0),
ta_mft_nr_override: Some(self.initial_manifest_number),
force: true
}
)
}
Expand Down
90 changes: 67 additions & 23 deletions src/cli/ta/signer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Managing the Trust Anchor Signer.

use std::sync::Arc;
use openssl::error::ErrorStack;
use rpki::ca::idexchange;
use rpki::uri;
use crate::ta;
Expand Down Expand Up @@ -93,6 +94,7 @@ pub struct SignerInitInfo {
pub tal_rsync: uri::Rsync,
pub private_key_pem: Option<String>,
pub ta_mft_nr_override: Option<u64>,
pub force: bool
}


Expand Down Expand Up @@ -131,30 +133,66 @@ impl TrustAnchorSignerManager {
&self,
info: SignerInitInfo,
) -> Result<Success, SignerClientError> {
if self.store.has(&self.ta_handle)? {
Err(SignerClientError::other(
"Trust Anchor Signer was already initialised.",
))
} else {
let cmd = TrustAnchorSignerInitCommand::new(
&self.ta_handle,
TrustAnchorSignerInitCommandDetails {
proxy_id: info.proxy_id,
repo_info: info.repo_info,
tal_https: info.tal_https,
tal_rsync: info.tal_rsync,
private_key_pem: info.private_key_pem,
ta_mft_nr_override: info.ta_mft_nr_override,
timing: self.config.ta_timing,
signer: self.signer.clone(),
},
&self.actor,
);

self.store.add(cmd)?;

Ok(Success)
if let Ok(cert) = self.store.get_latest(&self.ta_handle) {
if !info.force {
return Err(SignerClientError::other(
"Trust Anchor Signer was already initialised.",
));
}
if let Some(priv_key) = &info.private_key_pem {
let res = || -> Result<(Vec<u8>, Vec<u8>), ErrorStack> {
let priv_key = openssl::pkey::PKey::private_key_from_pem(
priv_key.as_bytes()
)?;
let signer_info = cert.get_signer_info();
let pub_key = signer_info.ta_cert_details
.cert().csr_info().key();
let k1 = priv_key.public_key_to_der()?;
let k2 = pub_key.to_info_bytes().to_vec();
Ok((k1, k2))
}();
if let Ok((k1, k2)) = res {
if k1 != k2 {
return Err(SignerClientError::other(
"You are not using the same private key."
));
}
} else if let Err(e) = res {
return Err(SignerClientError::other(
e.to_string()
));
}

if let Err(e) = self.store.drop(&self.ta_handle) {
return Err(SignerClientError::other(
e.to_string(),
));
}
} else {
return Err(SignerClientError::other(
"Private key must be provided when force reinitialising."
));
}
}
let cmd = TrustAnchorSignerInitCommand::new(
&self.ta_handle,
TrustAnchorSignerInitCommandDetails {
proxy_id: info.proxy_id,
repo_info: info.repo_info,
tal_https: info.tal_https,
tal_rsync: info.tal_rsync,
private_key_pem: info.private_key_pem,
ta_mft_nr_override: info.ta_mft_nr_override,
force_recreate: info.force,
timing: self.config.ta_timing,
signer: self.signer.clone(),
},
&self.actor,
);

self.store.add(cmd)?;

Ok(Success)
}

pub fn show(&self) -> Result<TrustAnchorSignerInfo, SignerClientError> {
Expand Down Expand Up @@ -220,3 +258,9 @@ impl TrustAnchorSignerManager {
}
}

impl TrustAnchorSignerManager {
pub fn get_krill_signer(&self) -> Arc<KrillSigner> {
self.signer.clone()
}
}

2 changes: 1 addition & 1 deletion src/commons/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ impl fmt::Display for Error {
Error::TaProxyAlreadyHasRepository => write!(f, "Trust Anchor Proxy already has repository"),
Error::TaProxyHasNoRepository => write!(f, "Trust Anchor Proxy has no repository"),
Error::TaProxyHasNoSigner => write!(f, "Trust Anchor Proxy has no associated signer"),
Error::TaProxyAlreadyHasSigner => write!(f, "Trust Anchor Proxy already has associated signer"),
Error::TaProxyAlreadyHasSigner => write!(f, "Trust Anchor Proxy already has associated signer with a different key identifier"),
Error::TaProxyHasNoRequest => write!(f, "Trust Anchor Proxy has no signer request"),
Error::TaProxyHasRequest => write!(f, "Trust Anchor Proxy already has signer request"),
Error::TaProxyRequestNonceMismatch(rcvd, expected) => write!(f, "Trust Anchor Response nonce '{}' does not match open Request nonce '{}'", rcvd, expected),
Expand Down
8 changes: 8 additions & 0 deletions src/commons/eventsourcing/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ where
.map_err(AggregateStoreError::KeyStoreError)
}

/// Returns Ok() if key was found and dropped
pub fn drop(&self, id: &MyHandle) -> Result<(), AggregateStoreError> {
let init_command_key = Self::key_for_command(id, 0);
self.kv
.drop_key(&init_command_key)
.map_err(AggregateStoreError::KeyStoreError)
}

/// Lists all known ids.
pub fn list(&self) -> Result<Vec<MyHandle>, AggregateStoreError> {
self.aggregates()
Expand Down
1 change: 1 addition & 0 deletions src/daemon/ca/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ impl CaManager {
ta_mft_nr_override: None,
timing: self.config.ta_timing,
signer: self.signer.clone(),
force_recreate: false
};
let cmd = TrustAnchorSignerInitCommand::new(
&handle,
Expand Down
1 change: 1 addition & 0 deletions src/ta/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ mod tests {
ta_mft_nr_override: Some(42),
timing,
signer: signer.clone(),
force_recreate: true
},
&actor,
);
Expand Down
9 changes: 5 additions & 4 deletions src/ta/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,11 +716,12 @@ impl TrustAnchorProxy {
&self,
signer: TrustAnchorSignerInfo,
) -> KrillResult<Vec<TrustAnchorProxyEvent>> {
if self.signer.is_none() {
Ok(vec![TrustAnchorProxyEvent::SignerAdded(signer)])
} else {
Err(Error::TaProxyAlreadyHasSigner)
if let Some(s) = &self.signer {
if s.ta_cert_details.cert().key_identifier() != signer.ta_cert_details.cert().key_identifier() {
return Err(Error::TaProxyAlreadyHasSigner);
}
}
Ok(vec![TrustAnchorProxyEvent::SignerAdded(signer)])
}

fn process_make_signer_request(
Expand Down
2 changes: 2 additions & 0 deletions src/ta/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ pub struct TrustAnchorSignerInitCommandDetails {
pub tal_rsync: uri::Rsync,
pub private_key_pem: Option<String>,
pub ta_mft_nr_override: Option<u64>,
pub force_recreate: bool,
pub timing: TaTimingConfig,
pub signer: Arc<KrillSigner>,
}
Expand Down Expand Up @@ -296,6 +297,7 @@ impl eventsourcing::Aggregate for TrustAnchorSigner {
timing.certificate_validity_years,
&signer,
)?;

let objects = TrustAnchorObjects::create(
ta_cert_details.cert(),
cmd.ta_mft_nr_override.unwrap_or(1),
Expand Down
Loading
Loading