mirror of
https://github.com/NLnetLabs/krill.git
synced 2026-09-27 11:54:52 +02:00
Register success/failure for RFC6492 messages sent to parents. (#250)
This commit is contained in:
+118
-1
@@ -20,7 +20,7 @@ use rpki::uri;
|
||||
use rpki::x509::{Serial, Time};
|
||||
|
||||
use crate::commons::api::publication::Publish;
|
||||
use crate::commons::api::{publication, RoaAggregateKey};
|
||||
use crate::commons::api::{publication, Entitlements, RoaAggregateKey};
|
||||
use crate::commons::api::{
|
||||
Base64, ChildHandle, ErrorResponse, Handle, HexEncodedHash, IssuanceRequest, ListReply, ParentCaContact,
|
||||
ParentHandle, RepositoryContact, RequestResourceLimit, RoaDefinition,
|
||||
@@ -1492,6 +1492,7 @@ pub enum ParentKindInfo {
|
||||
}
|
||||
|
||||
//------------ ParentInfo ----------------------------------------------------
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct ParentInfo {
|
||||
handle: ParentHandle,
|
||||
@@ -1515,6 +1516,122 @@ impl fmt::Display for ParentInfo {
|
||||
}
|
||||
}
|
||||
|
||||
//------------ ParentStatus --------------------------------------------------
|
||||
|
||||
pub struct AllParentStatuses(HashMap<Handle, ParentStatuses>);
|
||||
|
||||
impl AllParentStatuses {
|
||||
pub fn set_failure(&mut self, ca: &Handle, parent: &ParentHandle, error: ErrorResponse) {
|
||||
let status = self.get_mut_status(ca);
|
||||
status.set_failure(parent, error);
|
||||
}
|
||||
|
||||
pub fn set_last_updated(&mut self, ca: &Handle, parent: &ParentHandle) {
|
||||
self.get_mut_status(ca).set_last_updated(parent);
|
||||
}
|
||||
|
||||
pub fn set_entitlements(&mut self, ca: &Handle, parent: &ParentHandle, entitlements: &Entitlements) {
|
||||
self.get_mut_status(ca).set_entitlements(parent, entitlements)
|
||||
}
|
||||
|
||||
fn get_mut_status(&mut self, ca: &Handle) -> &mut ParentStatuses {
|
||||
if !self.0.contains_key(ca) {
|
||||
self.0.insert(ca.clone(), ParentStatuses::default());
|
||||
}
|
||||
|
||||
self.0.get_mut(ca).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AllParentStatuses {
|
||||
fn default() -> Self {
|
||||
AllParentStatuses(HashMap::new())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct ParentStatuses(HashMap<ParentHandle, ParentStatus>);
|
||||
|
||||
impl ParentStatuses {
|
||||
fn set_failure(&mut self, parent: &ParentHandle, error: ErrorResponse) {
|
||||
self.get_mut_status(parent).set_failure(error);
|
||||
}
|
||||
|
||||
fn set_entitlements(&mut self, parent: &ParentHandle, entitlements: &Entitlements) {
|
||||
self.get_mut_status(parent).set_entitlements(entitlements);
|
||||
}
|
||||
|
||||
fn set_last_updated(&mut self, parent: &ParentHandle) {
|
||||
self.get_mut_status(parent).set_last_updated();
|
||||
}
|
||||
|
||||
fn get_mut_status(&mut self, parent: &ParentHandle) -> &mut ParentStatus {
|
||||
if !self.0.contains_key(parent) {
|
||||
self.0.insert(parent.clone(), ParentStatus::default());
|
||||
}
|
||||
|
||||
self.0.get_mut(parent).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ParentStatuses {
|
||||
fn default() -> Self {
|
||||
ParentStatuses(HashMap::new())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct ParentStatus {
|
||||
last_exchange: Option<ParentExchange>,
|
||||
resources: HashMap<ResourceClassName, ResourceSet>,
|
||||
}
|
||||
|
||||
impl ParentStatus {
|
||||
fn set_failure(&mut self, error: ErrorResponse) {
|
||||
self.last_exchange = Some(ParentExchange {
|
||||
time: Time::now(),
|
||||
result: ParentExchangeResult::Failure(error),
|
||||
})
|
||||
}
|
||||
|
||||
fn set_entitlements(&mut self, entitlements: &Entitlements) {
|
||||
self.set_last_updated();
|
||||
self.resources = entitlements
|
||||
.classes()
|
||||
.iter()
|
||||
.map(|rc| (rc.class_name().clone(), rc.resource_set().clone()))
|
||||
.collect();
|
||||
}
|
||||
|
||||
fn set_last_updated(&mut self) {
|
||||
self.last_exchange = Some(ParentExchange {
|
||||
time: Time::now(),
|
||||
result: ParentExchangeResult::Success,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ParentStatus {
|
||||
fn default() -> Self {
|
||||
ParentStatus {
|
||||
last_exchange: None,
|
||||
resources: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct ParentExchange {
|
||||
time: Time,
|
||||
result: ParentExchangeResult,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum ParentExchangeResult {
|
||||
Success,
|
||||
Failure(ErrorResponse),
|
||||
}
|
||||
|
||||
//------------ CertAuthInfo --------------------------------------------------
|
||||
|
||||
/// This type represents the details of a CertAuth that need
|
||||
|
||||
@@ -16,6 +16,7 @@ use crate::commons::api::{
|
||||
};
|
||||
use crate::commons::eventsourcing::AggregateStoreError;
|
||||
use crate::commons::remote::rfc6492;
|
||||
use crate::commons::remote::rfc6492::NotPerformedResponse;
|
||||
use crate::commons::remote::rfc8181;
|
||||
use crate::commons::remote::rfc8181::ReportErrorCode;
|
||||
use crate::commons::util::httpclient;
|
||||
@@ -288,6 +289,9 @@ pub enum Error {
|
||||
#[display(fmt = "RFC 6492 Issue: {}", _0)]
|
||||
Rfc6492(rfc6492::Error),
|
||||
|
||||
#[display(fmt = "RFC 6492 Not Performed: {}", _0)]
|
||||
Rfc6492NotPerformed(NotPerformedResponse),
|
||||
|
||||
#[display(fmt = "Invalid CSR received: {}", _0)]
|
||||
Rfc6492InvalidCsrSent(String),
|
||||
|
||||
@@ -592,6 +596,7 @@ impl Error {
|
||||
// RFC6492 (requesting resources, not on JSON api)
|
||||
//-----------------------------------------------------------------
|
||||
Error::Rfc6492(e) => ErrorResponse::new("rfc6492-protocol", &self).with_cause(e),
|
||||
Error::Rfc6492NotPerformed(e) => ErrorResponse::new("rfc6492-not-performed-response", &self).with_cause(e),
|
||||
Error::Rfc6492InvalidCsrSent(e) => ErrorResponse::new("rfc6492-invalid-csr", &self).with_cause(e),
|
||||
Error::Rfc6492SignatureInvalid => ErrorResponse::new("rfc6492-invalid-signature", &self),
|
||||
|
||||
|
||||
+77
-35
@@ -10,11 +10,11 @@ use rpki::crypto::KeyIdentifier;
|
||||
use rpki::uri;
|
||||
|
||||
use crate::commons::api::{
|
||||
self, AddChildRequest, Base64, CaCommandDetails, CaCommandResult, CertAuthList, CertAuthSummary, ChildAuthRequest,
|
||||
ChildCaInfo, ChildHandle, CommandHistory, CommandHistoryCriteria, Entitlements, Handle, IssuanceRequest,
|
||||
IssuanceResponse, IssuedCert, ListReply, ParentCaContact, ParentCaReq, ParentHandle, PublishDelta, RcvdCert,
|
||||
RepoInfo, RepositoryContact, ResourceClassName, ResourceSet, RevocationRequest, RevocationResponse, StoredEffect,
|
||||
UpdateChildRequest,
|
||||
self, AddChildRequest, AllParentStatuses, Base64, CaCommandDetails, CaCommandResult, CertAuthList, CertAuthSummary,
|
||||
ChildAuthRequest, ChildCaInfo, ChildHandle, CommandHistory, CommandHistoryCriteria, Entitlements, ErrorResponse,
|
||||
Handle, IssuanceRequest, IssuanceResponse, IssuedCert, ListReply, ParentCaContact, ParentCaReq, ParentHandle,
|
||||
PublishDelta, RcvdCert, RepoInfo, RepositoryContact, ResourceClassName, ResourceSet, RevocationRequest,
|
||||
RevocationResponse, StoredEffect, UpdateChildRequest,
|
||||
};
|
||||
use crate::commons::error::Error;
|
||||
use crate::commons::eventsourcing::{Aggregate, AggregateStore, CommandKey, DiskAggregateStore};
|
||||
@@ -36,6 +36,7 @@ use crate::daemon::mq::EventQueueListener;
|
||||
pub struct CaServer<S: Signer> {
|
||||
signer: Arc<RwLock<S>>,
|
||||
ca_store: Arc<DiskAggregateStore<CertAuth<S>>>,
|
||||
parents_statuses: Arc<RwLock<AllParentStatuses>>,
|
||||
rfc8181_log_dir: Option<PathBuf>,
|
||||
rfc6492_log_dir: Option<PathBuf>,
|
||||
}
|
||||
@@ -56,6 +57,7 @@ impl<S: Signer> CaServer<S> {
|
||||
Ok(CaServer {
|
||||
signer,
|
||||
ca_store: Arc::new(ca_store),
|
||||
parents_statuses: Arc::new(RwLock::new(AllParentStatuses::default())),
|
||||
rfc6492_log_dir: rfc6492_log_dir.cloned(),
|
||||
rfc8181_log_dir: rfc8181_log_dir.cloned(),
|
||||
})
|
||||
@@ -510,13 +512,20 @@ impl<S: Signer> CaServer<S> {
|
||||
// No repo set, yet. So, skip updating.
|
||||
Ok(())
|
||||
} else {
|
||||
let entitlements = self.get_entitlements_from_parent(handle, parent).await?;
|
||||
match self.get_entitlements_from_parent(handle, parent).await {
|
||||
Err(e) => {
|
||||
self.set_parent_status_failure(handle, parent, e.to_error_response());
|
||||
Err(e)
|
||||
}
|
||||
Ok(entitlements) => {
|
||||
self.set_parent_status_entitlements(handle, parent, &entitlements);
|
||||
if !self.update_resource_classes(handle, parent.clone(), entitlements)? {
|
||||
return Ok(()); // Nothing to do
|
||||
}
|
||||
|
||||
if !self.update_resource_classes(handle, parent.clone(), entitlements)? {
|
||||
return Ok(()); // Nothing to do
|
||||
Ok(()) // Pending requests will be picked up by the scheduler.
|
||||
}
|
||||
}
|
||||
|
||||
Ok(()) // Pending requests will be picked up by the scheduler.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -568,8 +577,19 @@ impl<S: Signer> CaServer<S> {
|
||||
.await
|
||||
}
|
||||
ParentCaContact::Rfc6492(parent_res) => {
|
||||
self.send_revoke_requests_rfc6492(revoke_requests, child.id_key(), parent_res)
|
||||
match self
|
||||
.send_revoke_requests_rfc6492(revoke_requests, child.id_key(), parent_res)
|
||||
.await
|
||||
{
|
||||
Err(e) => {
|
||||
self.set_parent_status_failure(handle, parent, e.to_error_response());
|
||||
Err(e)
|
||||
}
|
||||
Ok(res) => {
|
||||
self.set_parent_status_updated(handle, parent);
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -628,17 +648,15 @@ impl<S: Signer> CaServer<S> {
|
||||
|
||||
let revoke = rfc6492::Message::revoke(sender, recipient, req.clone());
|
||||
|
||||
match self
|
||||
let response = self
|
||||
.send_rfc6492_and_validate_response(signing_key, parent_res, revoke.into_bytes(), Some(cms_logger))
|
||||
.await
|
||||
{
|
||||
Err(e) => error!("Could not send/validate revoke: {}", e),
|
||||
Ok(response) => match response {
|
||||
rfc6492::Res::Revoke(revoke_response) => revocations.push(revoke_response),
|
||||
rfc6492::Res::NotPerformed(e) => error!("We got an error response: {}", e),
|
||||
rfc6492::Res::List(_) => error!("List response to revoke request??"),
|
||||
rfc6492::Res::Issue(_) => error!("Issue response to revoke request??"),
|
||||
},
|
||||
.await?;
|
||||
|
||||
match response {
|
||||
rfc6492::Res::Revoke(revoke_response) => revocations.push(revoke_response),
|
||||
rfc6492::Res::NotPerformed(e) => return Err(Error::Rfc6492NotPerformed(e)),
|
||||
rfc6492::Res::List(_) => return Err(Error::custom("Got a List response to revoke request??")),
|
||||
rfc6492::Res::Issue(_) => return Err(Error::custom("Issue response to revoke request??")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,8 +674,19 @@ impl<S: Signer> CaServer<S> {
|
||||
ParentCaContact::Ta(_) => Err(Error::TaNotAllowed),
|
||||
ParentCaContact::Embedded => self.send_cert_requests_embedded(cert_requests, handle, parent),
|
||||
ParentCaContact::Rfc6492(parent_res) => {
|
||||
self.send_cert_requests_rfc6492(cert_requests, child.id_key(), &parent_res)
|
||||
match self
|
||||
.send_cert_requests_rfc6492(cert_requests, child.id_key(), &parent_res)
|
||||
.await
|
||||
{
|
||||
Err(e) => {
|
||||
self.set_parent_status_failure(handle, parent, e.to_error_response());
|
||||
Err(e)
|
||||
}
|
||||
Ok(res) => {
|
||||
self.set_parent_status_updated(handle, parent);
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
}?;
|
||||
|
||||
@@ -724,20 +753,18 @@ impl<S: Signer> CaServer<S> {
|
||||
|
||||
let issue = rfc6492::Message::issue(sender, recipient, req);
|
||||
|
||||
match self
|
||||
let response = self
|
||||
.send_rfc6492_and_validate_response(signing_key, parent_res, issue.into_bytes(), Some(cms_logger))
|
||||
.await
|
||||
{
|
||||
Err(e) => error!("Could not send/validate csr: {}", e),
|
||||
Ok(response) => match response {
|
||||
rfc6492::Res::NotPerformed(e) => error!("We got an error response: {}", e),
|
||||
rfc6492::Res::Issue(issue_response) => {
|
||||
let (_, _, _, issued) = issue_response.unwrap();
|
||||
issued_certs.push(issued);
|
||||
}
|
||||
rfc6492::Res::List(_) => error!("List reply to issue request??"),
|
||||
rfc6492::Res::Revoke(_) => error!("Revoke reply to issue request??"),
|
||||
},
|
||||
.await?;
|
||||
|
||||
match response {
|
||||
rfc6492::Res::NotPerformed(e) => return Err(Error::Rfc6492NotPerformed(e)),
|
||||
rfc6492::Res::Issue(issue_response) => {
|
||||
let (_, _, _, issued) = issue_response.unwrap();
|
||||
issued_certs.push(issued);
|
||||
}
|
||||
rfc6492::Res::List(_) => return Err(Error::custom("List reply to issue request??")),
|
||||
rfc6492::Res::Revoke(_) => return Err(Error::custom("Revoke reply to issue request??")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -843,6 +870,21 @@ impl<S: Signer> CaServer<S> {
|
||||
.into_reply()
|
||||
.map_err(Error::custom)
|
||||
}
|
||||
|
||||
fn set_parent_status_failure(&self, ca: &Handle, parent: &ParentHandle, error: ErrorResponse) {
|
||||
self.parents_statuses.write().unwrap().set_failure(ca, parent, error);
|
||||
}
|
||||
|
||||
fn set_parent_status_entitlements(&self, ca: &Handle, parent: &ParentHandle, entitlements: &Entitlements) {
|
||||
self.parents_statuses
|
||||
.write()
|
||||
.unwrap()
|
||||
.set_entitlements(ca, parent, entitlements);
|
||||
}
|
||||
|
||||
fn set_parent_status_updated(&self, ca: &Handle, parent: &ParentHandle) {
|
||||
self.parents_statuses.write().unwrap().set_last_updated(ca, parent);
|
||||
}
|
||||
}
|
||||
|
||||
/// # Support sending publication messages, and verifying responses.
|
||||
|
||||
Reference in New Issue
Block a user