mirror of
https://github.com/NLnetLabs/krill.git
synced 2026-09-28 04:14:53 +02:00
Revoke unexpected surplus keys at the parent. (fixes: #200)
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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>>,
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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 '{}'.",
|
||||
|
||||
Reference in New Issue
Block a user