Revoke unexpected surplus keys at the parent. (fixes: #200)

This commit is contained in:
Tim Bruijnzeels
2020-02-19 11:48:22 +01:00
parent 3698cdee7d
commit 21663f1e8b
8 changed files with 86 additions and 5 deletions
+13 -1
View File
@@ -286,6 +286,9 @@ impl<S: Signer> Aggregate for CertAuth<S> {
.unwrap()
.old_key_removed();
}
EvtDet::UnexpectedKeyFound(_, _) => {
// no action needed, this is marked to flag that a key may be removed
}
//-----------------------------------------------------------------------
// Route Authorizations
@@ -955,6 +958,15 @@ impl<S: Signer> CertAuth<S> {
.ok_or_else(|| Error::CaParentUnknown(self.handle.clone(), parent.clone()))
}
/// Find the parent for a given resource class name.
pub fn parent_for_rc(&self, rcn: &ResourceClassName) -> KrillResult<&ParentHandle> {
let rc = self
.resources
.get(rcn)
.ok_or_else(|| Error::ResourceClassUnknown(rcn.clone()))?;
Ok(rc.parent_handle())
}
/// Adds a parent. This method will return an error in case a parent
/// by this name (handle) is already known.
fn add_parent(&self, parent: Handle, info: ParentCaContact) -> KrillResult<Vec<Evt>> {
@@ -1053,7 +1065,7 @@ impl<S: Signer> CertAuth<S> {
) -> KrillResult<Vec<Evt>> {
let repo = self.get_repository_contact()?;
let parent_class_name = entitlement.class_name().clone();
let req_details_list = rc.make_request_events(entitlement, repo.repo_info(), signer)?;
let req_details_list = rc.make_entitlement_events(entitlement, repo.repo_info(), signer)?;
let mut res = vec![];
for details in req_details_list.into_iter() {
+6
View File
@@ -247,6 +247,7 @@ pub enum EvtDet {
KeyPendingToActive(ResourceClassName, CertifiedKey, ObjectsDelta),
KeyRollActivated(ResourceClassName, RevocationRequest),
KeyRollFinished(ResourceClassName, ObjectsDelta),
UnexpectedKeyFound(ResourceClassName, RevocationRequest),
// Route Authorizations
RouteAuthorizationAdded(RouteAuthorization),
@@ -555,6 +556,11 @@ impl fmt::Display for EvtDet {
"key roll: finished for resource class '{}'",
rcn
),
EvtDet::UnexpectedKeyFound(rcn, revoke) => write!(
f,
"Found unexpected key in resource class '{}', will try to revoke key id: '{}'",
rcn, revoke.key()
),
// Route Authorizations
EvtDet::RouteAuthorizationAdded(route) => write!(
+24 -1
View File
@@ -323,7 +323,7 @@ impl KeyState {
}
}
pub fn request_certs<S: Signer>(
pub fn make_entitlement_events<S: Signer>(
&self,
rcn: ResourceClassName,
entitlement: &EntitlementClass,
@@ -379,6 +379,17 @@ impl KeyState {
res.push(EvtDet::CertificateRequested(rcn.clone(), req, *key_id));
}
for key in entitlement
.issued()
.iter()
.map(|c| c.subject_key_identifier())
{
if !self.knows_key(key) {
let revocation = RevocationRequest::new(entitlement.class_name().clone(), key);
res.push(EvtDet::UnexpectedKeyFound(rcn.clone(), revocation));
}
}
Ok(res)
}
@@ -572,4 +583,16 @@ impl KeyState {
_ => false,
}
}
fn knows_key(&self, key_id: KeyIdentifier) -> bool {
match self {
KeyState::Pending(pending) => pending.key_id == key_id,
KeyState::Active(current) => current.key_id == key_id,
KeyState::RollPending(pending, current) => {
pending.key_id == key_id || current.key_id == key_id
}
KeyState::RollNew(new, current) => new.key_id == key_id || current.key_id == key_id,
KeyState::RollOld(current, old) => current.key_id == key_id || old.key_id == key_id,
}
}
}
+7 -2
View File
@@ -327,13 +327,18 @@ impl ResourceClass {
}
/// Request certificates for any key that needs it.
pub fn make_request_events<S: Signer>(
/// Also, create revocation events for any unexpected keys to recover from
/// issues where the parent believes we have keys that we do not know. This
/// can happen in corner cases where re-initialisation of Krill as a child
/// is done without proper revocation at the parent, or as is the case with
/// ARIN - Krill is sometimes told to just drop all resources.
pub fn make_entitlement_events<S: Signer>(
&self,
entitlement: &EntitlementClass,
base_repo: &RepoInfo,
signer: &S,
) -> KrillResult<Vec<EvtDet>> {
self.key_state.request_certs(
self.key_state.make_entitlement_events(
self.name.clone(),
entitlement,
base_repo,
+14
View File
@@ -578,6 +578,20 @@ impl<S: Signer> CaServer<S> {
}
}
pub fn send_revoke_unexpected_key(
&self,
handle: &Handle,
rcn: ResourceClassName,
revocation: RevocationRequest,
) -> KrillResult<HashMap<ResourceClassName, Vec<RevocationResponse>>> {
let child = self.ca_store.get_latest(handle)?;
let parent = child.parent_for_rc(&rcn)?;
let mut requests = HashMap::new();
requests.insert(rcn, vec![revocation]);
self.send_revoke_requests(handle, parent, requests)
}
fn send_revoke_requests_embedded(
&self,
revoke_requests: HashMap<ResourceClassName, Vec<RevocationRequest>>,
+1 -1
View File
@@ -656,7 +656,7 @@ pub fn ca_add_parent_xml(
};
let req = if string.starts_with("<repository") {
return server_error(Error::CaParentResponseWrongXml(ca.clone()));
return server_error(Error::CaParentResponseWrongXml(ca));
} else {
let res = match rfc8183::ParentResponse::validate(string.as_bytes())
.map_err(|e| Error::CaParentResponseInvalidXml(ca.clone(), e.to_string()))
+8
View File
@@ -38,6 +38,14 @@ pub enum QueueEvent {
HashMap<ResourceClassName, Vec<RevocationRequest>>,
),
#[display(
fmt = "unexpected key found for '{}' version '{}' resource class: '{}'",
_0,
_1,
_2
)]
UnexpectedKey(Handle, u64, ResourceClassName, RevocationRequest),
#[display(fmt = "clean up old repo *if it exists* for '{}' version '{}'", _0, _1)]
CleanOldRepo(Handle, u64),
}
+13
View File
@@ -80,6 +80,19 @@ fn make_event_sh(
just before removing the resource class entitlements.");
}
}
QueueEvent::UnexpectedKey(handle, _, rcn, revocation) => {
trace!(
"Trigger sending revocation requests for unexpected key with id '{}' in RC '{}'",
revocation.key(),
rcn
);
if caserver
.send_revoke_unexpected_key(&handle, rcn, revocation)
.is_err()
{
debug!("Could not revoke unexpected surplus key at parent.");
}
}
QueueEvent::ParentAdded(handle, _, parent) => {
trace!(
"Get updates for '{}' from added parent '{}'.",