mirror of
https://github.com/NLnetLabs/krill.git
synced 2026-09-20 08:27:49 +02:00
Force re-issuance of ROAs on upgrade from before 0.9.3-rc2 (#704)
This commit is contained in:
@@ -469,6 +469,7 @@ pub enum StorableCaCommand {
|
||||
updates: RoaDefinitionUpdates,
|
||||
},
|
||||
ReissueBeforeExpiring,
|
||||
ForceReissue,
|
||||
RepoUpdate {
|
||||
service_uri: ServiceUri,
|
||||
},
|
||||
@@ -574,6 +575,7 @@ impl WithStorableDetails for StorableCaCommand {
|
||||
}
|
||||
|
||||
StorableCaCommand::ReissueBeforeExpiring => CommandSummary::new("cmd-ca-reissue-before-expiring", &self),
|
||||
StorableCaCommand::ForceReissue => CommandSummary::new("cmd-ca-force-reissue", &self),
|
||||
|
||||
// RTA
|
||||
StorableCaCommand::RtaPrepare { name } => {
|
||||
@@ -719,6 +721,9 @@ impl fmt::Display for StorableCaCommand {
|
||||
StorableCaCommand::ReissueBeforeExpiring => {
|
||||
write!(f, "Automatically re-issue objects before they would expire")
|
||||
}
|
||||
StorableCaCommand::ForceReissue => {
|
||||
write!(f, "Force re-issuance of objects")
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Publishing
|
||||
|
||||
@@ -23,6 +23,7 @@ use crate::{
|
||||
util::{httpclient, softsigner::SignerError},
|
||||
},
|
||||
daemon::{ca::RouteAuthorization, http::tls_keys},
|
||||
upgrades::UpgradeError,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
@@ -168,6 +169,7 @@ pub enum Error {
|
||||
HttpsSetup(String),
|
||||
HttpClientError(httpclient::Error),
|
||||
ConfigError(String),
|
||||
UpgradeError(UpgradeError),
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// General API Client Issues
|
||||
@@ -315,6 +317,7 @@ impl fmt::Display for Error {
|
||||
Error::HttpsSetup(e) => write!(f, "Cannot set up HTTPS: {}", e),
|
||||
Error::HttpClientError(e) => write!(f, "HTTP client error: {}", e),
|
||||
Error::ConfigError(e) => write!(f, "Configuration error: {}", e),
|
||||
Error::UpgradeError(e) => write!(f, "Could not upgrade Krill: {}", e),
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// General API Client Issues
|
||||
@@ -542,6 +545,12 @@ impl From<PublicationDeltaError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UpgradeError> for Error {
|
||||
fn from(e: UpgradeError) -> Self {
|
||||
Error::UpgradeError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn signer(e: impl Display) -> Self {
|
||||
Error::SignerError(e.to_string())
|
||||
@@ -622,6 +631,9 @@ impl Error {
|
||||
// internal configuration error
|
||||
Error::ConfigError(e) => ErrorResponse::new("sys-config", &self).with_cause(e),
|
||||
|
||||
// upgrade error
|
||||
Error::UpgradeError(e) => ErrorResponse::new("sys-upgrade", &self).with_cause(e),
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
// General API Client Issues (label: api-*)
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
@@ -442,7 +442,12 @@ impl Aggregate for CertAuth {
|
||||
CmdDet::RouteAuthorizationsUpdate(updates, config, signer) => {
|
||||
self.route_authorizations_update(updates, &config, signer)
|
||||
}
|
||||
CmdDet::RouteAuthorizationsRenew(config, signer) => self.route_authorizations_renew(&config, &signer),
|
||||
CmdDet::RouteAuthorizationsRenew(config, signer) => {
|
||||
self.route_authorizations_renew(false, &config, &signer)
|
||||
}
|
||||
CmdDet::RouteAuthorizationsForceRenew(config, signer) => {
|
||||
self.route_authorizations_renew(true, &config, &signer)
|
||||
}
|
||||
|
||||
// Republish
|
||||
CmdDet::RepoUpdate(contact, signer) => self.update_repo(contact, &signer),
|
||||
@@ -1622,16 +1627,25 @@ impl CertAuth {
|
||||
}
|
||||
|
||||
/// Renew existing ROA objects if needed.
|
||||
pub fn route_authorizations_renew(&self, config: &Config, signer: &KrillSigner) -> KrillResult<Vec<CaEvt>> {
|
||||
pub fn route_authorizations_renew(
|
||||
&self,
|
||||
force: bool,
|
||||
config: &Config,
|
||||
signer: &KrillSigner,
|
||||
) -> KrillResult<Vec<CaEvt>> {
|
||||
let mut evt_dets = vec![];
|
||||
|
||||
for (rcn, rc) in self.resources.iter() {
|
||||
let updates = rc.renew_roas(&config.issuance_timing, signer)?;
|
||||
let updates = rc.renew_roas(force, &config.issuance_timing, signer)?;
|
||||
if updates.contains_changes() {
|
||||
info!(
|
||||
"CA '{}' reissued ROAs under RC '{}' before they would expire: {}",
|
||||
self.handle, rcn, updates
|
||||
);
|
||||
if force {
|
||||
info!("CA '{}' reissued all ROAs under RC '{}'", self.handle, rcn);
|
||||
} else {
|
||||
info!(
|
||||
"CA '{}' reissued ROAs under RC '{}' before they would expire: {}",
|
||||
self.handle, rcn, updates
|
||||
);
|
||||
}
|
||||
|
||||
evt_dets.push(CaEvtDet::RoasUpdated {
|
||||
resource_class_name: rcn.clone(),
|
||||
|
||||
@@ -145,6 +145,9 @@ pub enum CmdDet {
|
||||
// will only be stored if there any updates to be done.
|
||||
RouteAuthorizationsRenew(Arc<Config>, Arc<KrillSigner>),
|
||||
|
||||
// Re-issue all ROA objects regardless of their expiration time.
|
||||
RouteAuthorizationsForceRenew(Arc<Config>, Arc<KrillSigner>),
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Publishing
|
||||
// ------------------------------------------------------------
|
||||
@@ -269,6 +272,7 @@ impl From<CmdDet> for StorableCaCommand {
|
||||
updates: updates.into(),
|
||||
},
|
||||
CmdDet::RouteAuthorizationsRenew(_, _) => StorableCaCommand::ReissueBeforeExpiring,
|
||||
CmdDet::RouteAuthorizationsForceRenew(_, _) => StorableCaCommand::ForceReissue,
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Publishing
|
||||
|
||||
@@ -341,7 +341,7 @@ impl RoaUpdates {
|
||||
impl fmt::Display for RoaUpdates {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if !self.updated.is_empty() {
|
||||
write!(f, "Added single VRP ROAs: ")?;
|
||||
write!(f, "Updated single VRP ROAs: ")?;
|
||||
for roa in self.updated.keys() {
|
||||
write!(f, "{} ", ObjectName::from(roa))?;
|
||||
}
|
||||
@@ -353,7 +353,7 @@ impl fmt::Display for RoaUpdates {
|
||||
}
|
||||
}
|
||||
if !self.aggregate_updated.is_empty() {
|
||||
write!(f, "Added ASN aggregated ROAs: ")?;
|
||||
write!(f, "Updated ASN aggregated ROAs: ")?;
|
||||
for roa in self.aggregate_updated.keys() {
|
||||
write!(f, "{} ", ObjectName::from(roa))?;
|
||||
}
|
||||
|
||||
@@ -1809,6 +1809,24 @@ impl CaManager {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Force the reissuance of all ROAs in all CAs. This function was added
|
||||
/// because we need to re-issue ROAs in Krill 0.9.3 to force that a short
|
||||
/// subject CN is used for the EE certificate: i.e. the SKI rather than the
|
||||
/// full public key. But there may also be other cases in future where
|
||||
/// forcing to re-issue ROAs may be useful.
|
||||
pub async fn force_renew_roas_all(&self, actor: &Actor) -> KrillResult<()> {
|
||||
for ca in self.ca_store.list()? {
|
||||
let cmd = Cmd::new(
|
||||
&ca,
|
||||
None,
|
||||
CmdDet::RouteAuthorizationsForceRenew(self.config.clone(), self.signer.clone()),
|
||||
actor,
|
||||
);
|
||||
self.send_command(cmd).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// # Resource Tagged Attestation functions
|
||||
|
||||
+7
-2
@@ -647,9 +647,14 @@ impl ResourceClass {
|
||||
impl ResourceClass {
|
||||
/// Renew all ROAs under the current for which the not-after time closer
|
||||
/// than the given number of weeks
|
||||
pub fn renew_roas(&self, issuance_timing: &IssuanceTimingConfig, signer: &KrillSigner) -> KrillResult<RoaUpdates> {
|
||||
pub fn renew_roas(
|
||||
&self,
|
||||
force: bool,
|
||||
issuance_timing: &IssuanceTimingConfig,
|
||||
signer: &KrillSigner,
|
||||
) -> KrillResult<RoaUpdates> {
|
||||
let key = self.get_current_key()?;
|
||||
self.roas.renew(key, issuance_timing, signer)
|
||||
self.roas.renew(force, key, issuance_timing, signer)
|
||||
}
|
||||
|
||||
/// Publish all ROAs under the new key
|
||||
|
||||
@@ -657,6 +657,7 @@ impl Roas {
|
||||
/// Re-new ROAs before they would expire
|
||||
pub fn renew(
|
||||
&self,
|
||||
force: bool,
|
||||
certified_key: &CertifiedKey,
|
||||
issuance_timing: &IssuanceTimingConfig,
|
||||
signer: &KrillSigner,
|
||||
@@ -667,7 +668,7 @@ impl Roas {
|
||||
|
||||
for (auth, roa_info) in self.simple.iter() {
|
||||
let name = ObjectName::from(auth);
|
||||
if roa_info.expires() < renew_threshold {
|
||||
if force || roa_info.expires() < renew_threshold {
|
||||
let roa = Self::make_roa(
|
||||
&[*auth],
|
||||
&name,
|
||||
@@ -684,7 +685,7 @@ impl Roas {
|
||||
for (roa_key, aggregate) in self.aggregate.iter() {
|
||||
let roa_info = aggregate.roa_info();
|
||||
|
||||
if roa_info.expires() < renew_threshold {
|
||||
if force || roa_info.expires() < renew_threshold {
|
||||
let authorizations = aggregate.authorizations().clone();
|
||||
let name = ObjectName::from(roa_key);
|
||||
let new_roa = Self::make_roa(
|
||||
|
||||
@@ -45,7 +45,7 @@ use crate::{
|
||||
},
|
||||
krillserver::KrillServer,
|
||||
},
|
||||
upgrades::{pre_start_upgrade, update_storage_version},
|
||||
upgrades::{post_start_upgrade, pre_start_upgrade, update_storage_version},
|
||||
};
|
||||
use hyper::{
|
||||
header::HeaderName,
|
||||
@@ -115,15 +115,17 @@ pub async fn start_krill_daemon(config: Arc<Config>) -> Result<(), Error> {
|
||||
test_data_dirs_or_die(&config);
|
||||
|
||||
// Call upgrade, this will only do actual work if needed.
|
||||
pre_start_upgrade(config.clone()).map_err(|e| Error::Custom(format!("Could not upgrade Krill: {}", e)))?;
|
||||
pre_start_upgrade(config.clone())?;
|
||||
|
||||
// Create the server, this will create the necessary data sub-directories if needed
|
||||
let krill = KrillServer::build(config.clone()).await?;
|
||||
|
||||
// Call post-start upgrades to trigger any upgrade related runtime actions, such as
|
||||
// re-issuing ROAs because subject name strategy has changed.
|
||||
post_start_upgrade(&config, &krill).await?;
|
||||
|
||||
// Update the version identifiers for the storage dirs
|
||||
update_storage_version(&config.data_dir)
|
||||
.map_err(|e| Error::Custom(format!("Could not upgrade Krill: {}", e)))
|
||||
.await?;
|
||||
update_storage_version(&config.data_dir).await?;
|
||||
|
||||
// If the operator wanted to do the upgrade only, now is a good time to report success and stop
|
||||
if env::var(KRILL_ENV_UPGRADE_ONLY).is_ok() {
|
||||
|
||||
@@ -699,6 +699,11 @@ impl KrillServer {
|
||||
.suggest(definitions.as_slice(), &resources_held, limit)
|
||||
.await)
|
||||
}
|
||||
|
||||
/// Re-issue ROA objects so that they will use short subjects (see issue #700)
|
||||
pub async fn force_renew_roas(&self) -> KrillResult<()> {
|
||||
self.ca_manager.force_renew_roas_all(self.system_actor()).await
|
||||
}
|
||||
}
|
||||
|
||||
/// # Handle publication requests
|
||||
|
||||
+22
-9
@@ -14,7 +14,7 @@ use crate::{
|
||||
eventsourcing::{AggregateStoreError, CommandKey, KeyStoreKey, KeyValueError, KeyValueStore},
|
||||
util::{file, KrillVersion},
|
||||
},
|
||||
daemon::config::Config,
|
||||
daemon::{config::Config, krillserver::KrillServer},
|
||||
pubd::RepositoryManager,
|
||||
upgrades::v0_9_0::{CaObjectsMigration, PubdObjectsMigration},
|
||||
};
|
||||
@@ -34,7 +34,6 @@ pub enum UpgradeError {
|
||||
IoError(KrillIoError),
|
||||
Unrecognised(String),
|
||||
CannotLoadAggregate(Handle),
|
||||
KrillError(crate::commons::error::Error),
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
@@ -46,7 +45,6 @@ impl fmt::Display for UpgradeError {
|
||||
UpgradeError::IoError(e) => e.fmt(f),
|
||||
UpgradeError::Unrecognised(s) => write!(f, "Unrecognised command summary: {}", s),
|
||||
UpgradeError::CannotLoadAggregate(handle) => write!(f, "Cannot load: {}", handle),
|
||||
UpgradeError::KrillError(e) => e.fmt(f),
|
||||
UpgradeError::Custom(s) => s.fmt(f),
|
||||
}
|
||||
}
|
||||
@@ -81,7 +79,7 @@ impl From<KrillIoError> for UpgradeError {
|
||||
|
||||
impl From<crate::commons::error::Error> for UpgradeError {
|
||||
fn from(e: crate::commons::error::Error) -> Self {
|
||||
UpgradeError::KrillError(e)
|
||||
UpgradeError::Custom(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +158,18 @@ pub trait UpgradeStore {
|
||||
|
||||
/// Should be called when Krill starts, before the KrillServer is initiated
|
||||
pub fn pre_start_upgrade(config: Arc<Config>) -> Result<(), UpgradeError> {
|
||||
upgrade_0_9_0(config)
|
||||
upgrade_data_to_0_9_0(config)
|
||||
}
|
||||
|
||||
/// Should be called when the KrillServer is initiated, before the webserver is started
|
||||
/// and operators can make changes.
|
||||
pub async fn post_start_upgrade(config: &Config, server: &KrillServer) -> Result<(), UpgradeError> {
|
||||
if needs_upgrade(&config.data_dir, "cas", KrillVersion::candidate(0, 9, 3, 2)) {
|
||||
info!("Reissue ROAs on upgrade to force short EE certificate subjects in the objects");
|
||||
server.force_renew_roas().await.map_err(|e| e.into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_storage_version(work_dir: &Path) -> Result<(), UpgradeError> {
|
||||
@@ -179,7 +188,7 @@ pub async fn update_storage_version(work_dir: &Path) -> Result<(), UpgradeError>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn upgrade_0_9_0(config: Arc<Config>) -> Result<(), UpgradeError> {
|
||||
fn upgrade_data_to_0_9_0(config: Arc<Config>) -> Result<(), UpgradeError> {
|
||||
let work_dir = &config.data_dir;
|
||||
if needs_v0_9_0_upgrade(work_dir, "pubd") {
|
||||
PubdObjectsMigration::migrate(config.clone())?;
|
||||
@@ -196,11 +205,15 @@ fn upgrade_0_9_0(config: Arc<Config>) -> Result<(), UpgradeError> {
|
||||
}
|
||||
|
||||
fn needs_v0_9_0_upgrade(work_dir: &Path, ns: &str) -> bool {
|
||||
needs_upgrade(work_dir, ns, KrillVersion::release(0, 9, 0))
|
||||
}
|
||||
|
||||
fn needs_upgrade(work_dir: &Path, ns: &str, before: KrillVersion) -> bool {
|
||||
let keystore_path = work_dir.join(ns);
|
||||
if keystore_path.exists() {
|
||||
let version_path = keystore_path.join("version");
|
||||
let version_found = file::load_json(&version_path).unwrap_or_else(|_| KrillVersion::v0_5_0_or_before());
|
||||
version_found < KrillVersion::release(0, 9, 0)
|
||||
version_found < before
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@@ -227,7 +240,7 @@ mod tests {
|
||||
let config = Arc::new(Config::test(&work_dir, false, false, false));
|
||||
let _ = config.init_logging();
|
||||
|
||||
upgrade_0_9_0(config).unwrap();
|
||||
upgrade_data_to_0_9_0(config).unwrap();
|
||||
|
||||
let _ = fs::remove_dir_all(work_dir);
|
||||
}
|
||||
@@ -241,7 +254,7 @@ mod tests {
|
||||
let config = Arc::new(Config::test(&work_dir, false, false, false));
|
||||
let _ = config.init_logging();
|
||||
|
||||
upgrade_0_9_0(config).unwrap();
|
||||
upgrade_data_to_0_9_0(config).unwrap();
|
||||
|
||||
let _ = fs::remove_dir_all(work_dir);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user