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