From 84bdd0c4fad7c3cd69e3a0197ddd5b3dedd82bbf Mon Sep 17 00:00:00 2001 From: Tim Bruijnzeels Date: Wed, 14 Aug 2019 16:15:09 +0200 Subject: [PATCH] Force update resources for child CA. --- client/src/options.rs | 15 +- commons/src/api/admin.rs | 21 ++- commons/src/api/ca.rs | 167 +++++++++++++++-- commons/src/remote/rfc6492.rs | 5 +- daemon/src/ca/certauth.rs | 325 ++++++++++++++++++++++++++-------- daemon/src/ca/commands.rs | 39 ++-- daemon/src/ca/server.rs | 55 ++++-- daemon/src/ca/signing.rs | 31 ++++ daemon/src/mq.rs | 2 +- daemon/src/scheduler.rs | 6 +- daemon/tests/ca_under_ta.rs | 80 +++++++-- 11 files changed, 598 insertions(+), 148 deletions(-) diff --git a/client/src/options.rs b/client/src/options.rs index d08ac789..626216b4 100644 --- a/client/src/options.rs +++ b/client/src/options.rs @@ -177,8 +177,13 @@ impl Options { .help("Update the delegated IPv6 resources: e.g. 2001:db8::/32") .required(false) ) - - + .arg(Arg::with_name("force") + .short("f") + .long("force") + .takes_value(false) + .help("Force resource shrink now.") + .required(false) + ) ) ) ) @@ -441,7 +446,11 @@ impl Options { Some(resources) }; - let req = UpdateChildRequest::new(cert, resources); + let req = if m.is_present("force") { + UpdateChildRequest::force(cert, resources) + } else { + UpdateChildRequest::graceful(cert, resources) + }; command = Command::TrustAnchor(TrustAnchorCommand::UpdateChild(handle, req)) } diff --git a/commons/src/api/admin.rs b/commons/src/api/admin.rs index 050becda..2b205ac7 100644 --- a/commons/src/api/admin.rs +++ b/commons/src/api/admin.rs @@ -405,14 +405,31 @@ pub enum ChildAuthRequest { pub struct UpdateChildRequest { id_cert: Option, resources: Option, + force: bool, } impl UpdateChildRequest { - pub fn new(id_cert: Option, resources: Option) -> Self { - UpdateChildRequest { id_cert, resources } + pub fn graceful(id_cert: Option, resources: Option) -> Self { + UpdateChildRequest { + id_cert, + resources, + force: false, + } + } + + pub fn force(id_cert: Option, resources: Option) -> Self { + UpdateChildRequest { + id_cert, + resources, + force: true, + } } pub fn unpack(self) -> (Option, Option) { (self.id_cert, self.resources) } + + pub fn is_force(&self) -> bool { + self.force + } } diff --git a/commons/src/api/ca.rs b/commons/src/api/ca.rs index c57c3881..c1e0a544 100644 --- a/commons/src/api/ca.rs +++ b/commons/src/api/ca.rs @@ -10,6 +10,8 @@ use std::{fmt, ops}; use bytes::Bytes; use chrono::Duration; +use serde::de; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use rpki::cert::Cert; use rpki::crypto::KeyIdentifier; @@ -92,6 +94,10 @@ impl ChildCaDetails { &self.resources } + pub fn remove_resource(&mut self, class_name: &str) { + self.resources.remove(class_name); + } + /// This function will update the resource entitlements for an existing class /// or create a new class if needed pub fn set_resources_for_class(&mut self, class: &str, resources: ResourceSet) { @@ -127,20 +133,56 @@ impl ChildCaDetails { } /// This type defines a reference to PublicKey for easy storage and lookup. -#[derive(Clone, Debug, Deserialize, Display, Eq, Hash, PartialEq, Serialize)] -pub struct KeyRef(String); +#[derive(Clone, Debug, Display, Eq, Hash, PartialEq)] +pub struct KeyRef(KeyIdentifier); impl From<&KeyIdentifier> for KeyRef { fn from(ki: &KeyIdentifier) -> Self { - let hex = ki.into_hex(); - let s = unsafe { str::from_utf8_unchecked(&hex) }; - KeyRef(s.to_string()) + KeyRef(ki.clone()) + } +} + +impl From for KeyRef { + fn from(ki: KeyIdentifier) -> Self { + KeyRef(ki) + } +} + +impl From<&KeyRef> for KeyIdentifier { + fn from(kr: &KeyRef) -> Self { + kr.0.clone() + } +} + +impl From for KeyIdentifier { + fn from(kr: KeyRef) -> Self { + kr.0 } } impl From<&Cert> for KeyRef { fn from(c: &Cert) -> Self { - Self::from(&c.subject_key_identifier()) + KeyRef(c.subject_key_identifier()) + } +} + +impl Serialize for KeyRef { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.0.to_string().serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for KeyRef { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let string = String::deserialize(deserializer)?; + let ki = KeyIdentifier::from_str(&string).map_err(de::Error::custom)?; + Ok(KeyRef(ki)) } } @@ -154,7 +196,7 @@ impl From<&Cert> for KeyRef { #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct ChildResources { resources: ResourceSet, - since: Time, + shrink_pending: Option