Create real type for ResourceClassName.

This commit is contained in:
Tim Bruijnzeels
2019-08-19 11:18:00 +02:00
parent 60a60fd5d2
commit 7925e72e88
11 changed files with 230 additions and 128 deletions
+90 -20
View File
@@ -4,9 +4,8 @@
use std::collections::HashMap;
use std::convert::TryFrom;
use std::ops::{Deref, DerefMut};
use std::str;
use std::str::FromStr;
use std::{fmt, ops};
use std::str::{from_utf8_unchecked, FromStr};
use std::{fmt, ops, str};
use bytes::Bytes;
use chrono::Duration;
@@ -32,6 +31,75 @@ use crate::rpki::manifest::{FileAndHash, Manifest};
use crate::util::ext_serde;
use crate::util::softsigner::KeyId;
//------------ ResourceClassName -------------------------------------------
/// This type represents a resource class name, as used in RFC6492. The protocol
/// allows for any arbitrary set of utf8 characters to be used as the name, though
/// in practice names can be expected to be short and plain ascii or even numbers.
///
/// We store the name in a Bytes for cheap cloning, as these names need to be passed
/// around quite a bit and end up being stored as owned values in events.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ResourceClassName {
name: Bytes,
}
impl Default for ResourceClassName {
fn default() -> ResourceClassName {
ResourceClassName::from(0)
}
}
impl From<u32> for ResourceClassName {
fn from(nr: u32) -> ResourceClassName {
ResourceClassName {
name: Bytes::from(format!("{}", nr)),
}
}
}
impl From<&str> for ResourceClassName {
fn from(s: &str) -> ResourceClassName {
ResourceClassName {
name: Bytes::from(s),
}
}
}
impl From<String> for ResourceClassName {
fn from(s: String) -> ResourceClassName {
ResourceClassName {
name: Bytes::from(s),
}
}
}
impl fmt::Display for ResourceClassName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let s = unsafe { from_utf8_unchecked(self.name.as_ref()) };
write!(f, "{}", s)
}
}
impl Serialize for ResourceClassName {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
self.to_string().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for ResourceClassName {
fn deserialize<D>(deserializer: D) -> std::result::Result<ResourceClassName, D::Error>
where
D: Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
Ok(ResourceClassName::from(string))
}
}
//------------ ChildCaInfo ---------------------------------------------------
/// This type represents information about a child CA that is safe to share
@@ -40,7 +108,7 @@ use crate::util::softsigner::KeyId;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ChildCaInfo {
id_cert: Option<IdCert>,
resources: HashMap<String, ChildResources>,
resources: HashMap<ResourceClassName, ChildResources>,
}
impl ChildCaInfo {
@@ -48,11 +116,11 @@ impl ChildCaInfo {
self.id_cert.as_ref()
}
pub fn resources(&self) -> &HashMap<String, ChildResources> {
pub fn resources(&self) -> &HashMap<ResourceClassName, ChildResources> {
&self.resources
}
pub fn resources_for_class(&self, class: &str) -> Option<&ChildResources> {
pub fn resources_for_class(&self, class: &ResourceClassName) -> Option<&ChildResources> {
self.resources.get(class)
}
}
@@ -71,7 +139,7 @@ impl From<ChildCaDetails> for ChildCaInfo {
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ChildCaDetails {
id_cert: Option<IdCert>,
resources: HashMap<String, ChildResources>,
resources: HashMap<ResourceClassName, ChildResources>,
}
impl ChildCaDetails {
@@ -90,20 +158,20 @@ impl ChildCaDetails {
self.id_cert = Some(id_cert);
}
pub fn resources(&self) -> &HashMap<String, ChildResources> {
pub fn resources(&self) -> &HashMap<ResourceClassName, ChildResources> {
&self.resources
}
pub fn remove_resource(&mut self, class_name: &str) {
pub fn remove_resource(&mut self, class_name: &ResourceClassName) {
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) {
if self.resources.contains_key(class) {
pub fn set_resources_for_class(&mut self, class: ResourceClassName, resources: ResourceSet) {
if self.resources.contains_key(&class) {
self.resources
.get_mut(class)
.get_mut(&class)
.unwrap()
.set_resources(resources);
} else {
@@ -111,16 +179,15 @@ impl ChildCaDetails {
}
}
pub fn resources_for_class(&self, class: &str) -> Option<&ChildResources> {
pub fn resources_for_class(&self, class: &ResourceClassName) -> Option<&ChildResources> {
self.resources.get(class)
}
pub fn add_new_resource_class(&mut self, name: &str, resources: ResourceSet) {
self.resources
.insert(name.to_string(), ChildResources::new(resources));
pub fn add_new_resource_class(&mut self, name: ResourceClassName, resources: ResourceSet) {
self.resources.insert(name, ChildResources::new(resources));
}
pub fn add_cert(&mut self, class_name: &str, cert: IssuedCert) {
pub fn add_cert(&mut self, class_name: &ResourceClassName, cert: IssuedCert) {
// Note the resource class MUST exist, or no cert would have
// been issued to it. So, it's safe to unwrap here.
self.resources.get_mut(class_name).unwrap().add_cert(cert)
@@ -1568,18 +1635,21 @@ impl CertAuthInfo {
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct ParentCaInfo {
contact: ParentCaContact,
resources: HashMap<String, ResourceClassInfo>,
resources: HashMap<ResourceClassName, ResourceClassInfo>,
}
impl ParentCaInfo {
pub fn new(contact: ParentCaContact, resources: HashMap<String, ResourceClassInfo>) -> Self {
pub fn new(
contact: ParentCaContact,
resources: HashMap<ResourceClassName, ResourceClassInfo>,
) -> Self {
ParentCaInfo { contact, resources }
}
pub fn contact(&self) -> &ParentCaContact {
&self.contact
}
pub fn resources(&self) -> &HashMap<String, ResourceClassInfo> {
pub fn resources(&self) -> &HashMap<ResourceClassName, ResourceClassInfo> {
&self.resources
}
}
+38 -24
View File
@@ -5,11 +5,9 @@ use rpki::resources::{AsBlocks, IpBlocks};
use rpki::uri;
use rpki::x509::Time;
use crate::api::ca::{IssuedCert, RcvdCert, ResourceSet};
use crate::api::ca::{IssuedCert, RcvdCert, ResourceClassName, ResourceSet};
use crate::util::ext_serde;
pub const DFLT_CLASS: &str = "all";
//------------ ProvisioningRequest -------------------------------------------
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
@@ -51,10 +49,9 @@ impl Entitlements {
not_after: Time,
issued: Vec<IssuedCert>,
) -> Self {
let name = DFLT_CLASS.to_string();
Entitlements {
classes: vec![EntitlementClass {
class_name: name,
class_name: ResourceClassName::default(),
issuer,
resource_set,
not_after,
@@ -75,7 +72,7 @@ impl Entitlements {
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct EntitlementClass {
class_name: String,
class_name: ResourceClassName,
issuer: SigningCert,
resource_set: ResourceSet,
not_after: Time,
@@ -84,7 +81,7 @@ pub struct EntitlementClass {
impl EntitlementClass {
pub fn new(
class_name: String,
class_name: ResourceClassName,
issuer: SigningCert,
resource_set: ResourceSet,
not_after: Time,
@@ -99,7 +96,15 @@ impl EntitlementClass {
}
}
fn unwrap(self) -> (String, SigningCert, ResourceSet, Time, Vec<IssuedCert>) {
fn unwrap(
self,
) -> (
ResourceClassName,
SigningCert,
ResourceSet,
Time,
Vec<IssuedCert>,
) {
(
self.class_name,
self.issuer,
@@ -108,18 +113,23 @@ impl EntitlementClass {
self.issued,
)
}
pub fn class_name(&self) -> &str {
pub fn class_name(&self) -> &ResourceClassName {
&self.class_name
}
pub fn issuer(&self) -> &SigningCert {
&self.issuer
}
pub fn resource_set(&self) -> &ResourceSet {
&self.resource_set
}
pub fn not_after(&self) -> Time {
self.not_after
}
pub fn issued(&self) -> &Vec<IssuedCert> {
&self.issued
}
@@ -184,13 +194,13 @@ impl From<&RcvdCert> for SigningCert {
/// defined in section 3.4.1 of RFC6492.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IssuanceRequest {
class_name: String,
class_name: ResourceClassName,
limit: RequestResourceLimit,
csr: Csr,
}
impl IssuanceRequest {
pub fn new(class_name: String, limit: RequestResourceLimit, csr: Csr) -> Self {
pub fn new(class_name: ResourceClassName, limit: RequestResourceLimit, csr: Csr) -> Self {
IssuanceRequest {
class_name,
limit,
@@ -198,11 +208,11 @@ impl IssuanceRequest {
}
}
pub fn unwrap(self) -> (String, RequestResourceLimit, Csr) {
pub fn unwrap(self) -> (ResourceClassName, RequestResourceLimit, Csr) {
(self.class_name, self.limit, self.csr)
}
pub fn class_name(&self) -> &str {
pub fn class_name(&self) -> &ResourceClassName {
&self.class_name
}
pub fn limit(&self) -> &RequestResourceLimit {
@@ -232,7 +242,7 @@ impl Eq for IssuanceRequest {}
/// it includes the one certificate which has just been issued only.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct IssuanceResponse {
class_name: String,
class_name: ResourceClassName,
issuer: SigningCert,
resource_set: ResourceSet, // resources allowed on a cert
not_after: Time,
@@ -241,7 +251,7 @@ pub struct IssuanceResponse {
impl IssuanceResponse {
pub fn new(
class_name: String,
class_name: ResourceClassName,
issuer: SigningCert,
resource_set: ResourceSet, // resources allowed on a cert
not_after: Time,
@@ -256,22 +266,26 @@ impl IssuanceResponse {
}
}
pub fn unwrap(self) -> (String, SigningCert, ResourceSet, IssuedCert) {
pub fn unwrap(self) -> (ResourceClassName, SigningCert, ResourceSet, IssuedCert) {
(self.class_name, self.issuer, self.resource_set, self.issued)
}
pub fn class_name(&self) -> &str {
pub fn class_name(&self) -> &ResourceClassName {
&self.class_name
}
pub fn issuer(&self) -> &SigningCert {
&self.issuer
}
pub fn resource_set(&self) -> &ResourceSet {
&self.resource_set
}
pub fn not_after(&self) -> Time {
self.not_after
}
pub fn issued(&self) -> &IssuedCert {
&self.issued
}
@@ -354,16 +368,16 @@ impl Default for RequestResourceLimit {
/// defined in section 3.5.1 of RFC6492.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RevocationRequest {
class_name: String,
class_name: ResourceClassName,
key: KeyIdentifier,
}
impl RevocationRequest {
pub fn new(class_name: String, key: KeyIdentifier) -> Self {
pub fn new(class_name: ResourceClassName, key: KeyIdentifier) -> Self {
RevocationRequest { class_name, key }
}
pub fn class_name(&self) -> &str {
pub fn class_name(&self) -> &ResourceClassName {
&self.class_name
}
pub fn key(&self) -> &KeyIdentifier {
@@ -377,20 +391,20 @@ impl RevocationRequest {
/// defined in section 3.5.2 of RFC6492.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct RevocationResponse {
class_name: String,
class_name: ResourceClassName,
key: KeyIdentifier,
}
impl RevocationResponse {
pub fn new(class_name: String, key: KeyIdentifier) -> Self {
pub fn new(class_name: ResourceClassName, key: KeyIdentifier) -> Self {
RevocationResponse { class_name, key }
}
pub fn unpack(self) -> (String, KeyIdentifier) {
pub fn unpack(self) -> (ResourceClassName, KeyIdentifier) {
(self.class_name, self.key)
}
pub fn class_name(&self) -> &str {
pub fn class_name(&self) -> &ResourceClassName {
&self.class_name
}
pub fn key(&self) -> &KeyIdentifier {
+25 -15
View File
@@ -13,7 +13,7 @@ use rpki::uri;
use rpki::x509::Time;
use crate::api::admin::Handle;
use crate::api::ca::{IssuedCert, ResSetErr, ResourceSet};
use crate::api::ca::{IssuedCert, ResSetErr, ResourceClassName, ResourceSet};
use crate::api::{
EntitlementClass, Entitlements, IssuanceRequest, IssuanceResponse, RequestResourceLimit,
RevocationRequest, RevocationResponse, SigningCert,
@@ -296,7 +296,7 @@ impl Qry {
R: io::Read,
{
r.take_named_element("key", |mut a, _r| {
let class_name = a.take_req("class_name")?;
let class_name = ResourceClassName::from(a.take_req("class_name")?);
let ski = a.take_req("ski")?;
let ski_bytes = base64::decode_config(&ski, base64::URL_SAFE_NO_PAD)
.map_err(|_| Error::InvalidSki)?;
@@ -305,7 +305,7 @@ impl Qry {
let ski =
KeyIdentifier::try_from(ski_bytes.as_slice()).map_err(|_| Error::InvalidSki)?;
Ok(RevocationRequest::new(class_name.to_string(), ski))
Ok(RevocationRequest::new(class_name, ski))
})
}
@@ -314,7 +314,7 @@ impl Qry {
R: io::Read,
{
r.take_named_element("request", |mut a, r| {
let class_name = a.take_req("class_name")?;
let class_name = ResourceClassName::from(a.take_req("class_name")?);
let mut limit = RequestResourceLimit::default();
if let Some(asn) = a.take_opt("req_resource_set_as") {
@@ -335,7 +335,7 @@ impl Qry {
let csr_bytes = r.take_bytes_std()?;
let csr = Csr::decode(csr_bytes).map_err(|_| Error::InvalidCsr)?;
Ok(IssuanceRequest::new(class_name.to_string(), limit, csr))
Ok(IssuanceRequest::new(class_name, limit, csr))
})
}
}
@@ -372,9 +372,9 @@ impl Qry {
if let Some(v6) = limit.v6() {
attrs_strings.push(("req_resource_set_ipv6", v6.as_v6().to_string()));
}
attrs_strings.push(("class_name", class_name.to_string()));
let mut attrs_str = vec![];
attrs_str.push(("class_name", class_name));
let mut attrs_str: Vec<(&str, &str)> = vec![];
for (k, v) in &attrs_strings {
attrs_str.push((k, v.as_str()));
}
@@ -388,9 +388,13 @@ impl Qry {
rev: &RevocationRequest,
w: &mut XmlWriter<W>,
) -> Result<(), io::Error> {
let class_name = rev.class_name().to_string();
let bytes = rev.key().as_slice();
let encoded = base64::encode_config(bytes, base64::URL_SAFE_NO_PAD);
let att = [("class_name", rev.class_name()), ("ski", encoded.as_str())];
let att = [
("class_name", class_name.as_str()),
("ski", encoded.as_str()),
];
w.put_element("key", Some(&att), |w| w.empty())
}
}
@@ -453,7 +457,7 @@ impl Res {
R: io::Read,
{
r.take_named_element("class", |mut a, r| {
let name = a.take_req("class_name")?;
let name = ResourceClassName::from(a.take_req("class_name")?);
let cert_url = uri::Rsync::from_str(&a.take_req("cert_url")?)?;
let asn = a.take_req("resource_set_as")?;
@@ -503,7 +507,7 @@ impl Res {
{
r.take_opt_element(|t, mut a, r| match t.name.as_ref() {
"class" => {
let name = a.take_req("class_name")?;
let name = ResourceClassName::from(a.take_req("class_name")?);
let cert_url = uri::Rsync::from_str(&a.take_req("cert_url")?)?;
let asn = a.take_req("resource_set_as")?;
@@ -666,7 +670,7 @@ impl Res {
}
fn encode_class<'a, W: io::Write>(
class_name: &str,
class_name: &ResourceClassName,
cert_url: &uri::Rsync,
not_after: Time,
inrs: &ResourceSet,
@@ -675,6 +679,7 @@ impl Res {
w: &mut XmlWriter<W>,
) -> Result<(), io::Error> {
let cert_url = cert_url.to_string();
let class_name = class_name.to_string();
let not_after = not_after.to_rfc3339_opts(SecondsFormat::Secs, true);
let asn = inrs.asn().to_string();
@@ -684,7 +689,7 @@ impl Res {
let mut attrs = vec![];
attrs.push(("cert_url", cert_url.as_str()));
attrs.push(("class_name", class_name));
attrs.push(("class_name", class_name.as_str()));
attrs.push(("resource_set_as", asn.as_str()));
attrs.push(("resource_set_ipv4", v4.as_str()));
attrs.push(("resource_set_ipv6", v6.as_str()));
@@ -749,9 +754,13 @@ impl Res {
res: &RevocationResponse,
w: &mut XmlWriter<W>,
) -> Result<(), io::Error> {
let class_name = res.class_name().to_string();
let bytes = res.key().as_slice();
let encoded = base64::encode_config(bytes, base64::URL_SAFE_NO_PAD);
let att = [("class_name", res.class_name()), ("ski", encoded.as_str())];
let att = [
("class_name", class_name.as_str()),
("ski", encoded.as_str()),
];
w.put_element("key", Some(&att), |w| w.empty())
}
}
@@ -818,6 +827,7 @@ impl NotPerformedResponse {
2001,
"Internal Server Error - Request not performed",
)),
_ => Err(Error::InvalidErrorCode(code.to_string())),
}
}
@@ -1043,7 +1053,7 @@ mod tests {
let sender = "child".to_string();
let rcpt = "parent".to_string();
let class = "all".to_string();
let class = ResourceClassName::default();
let ski = cert.subject_public_key_info().key_identifier();
let revocation = RevocationRequest::new(class, ski);
@@ -1063,7 +1073,7 @@ mod tests {
let sender = "child".to_string();
let rcpt = "parent".to_string();
let class = "all".to_string();
let class = ResourceClassName::default();
let ski = cert.subject_public_key_info().key_identifier();
let revocation = RevocationResponse::new(class, ski);
+32 -28
View File
@@ -15,12 +15,12 @@ use krill_commons::api::admin::{
};
use krill_commons::api::ca::{
AddedObject, CertAuthInfo, ChildCaDetails, CurrentObject, IssuedCert, ObjectName, ObjectsDelta,
ParentCaInfo, PublicationDelta, RcvdCert, ReplacedObject, RepoInfo, ResourceSet, Revocation,
TrustAnchorInfo, UpdatedObject, WithdrawnObject,
ParentCaInfo, PublicationDelta, RcvdCert, ReplacedObject, RepoInfo, ResourceClassName,
ResourceSet, Revocation, TrustAnchorInfo, UpdatedObject, WithdrawnObject,
};
use krill_commons::api::{
self, EntitlementClass, Entitlements, IssuanceRequest, IssuanceResponse, RequestResourceLimit,
RevocationRequest, RevocationResponse, SigningCert, DFLT_CLASS,
RevocationRequest, RevocationResponse, SigningCert,
};
use krill_commons::eventsourcing::{Aggregate, StoredEvent};
use krill_commons::remote::builder::{IdCertBuilder, SignedMessageBuilder};
@@ -33,7 +33,7 @@ use krill_commons::util::softsigner::KeyId;
use crate::ca::signing::CertSiaInfo;
use crate::ca::{
self, ta_handle, ChildHandle, Cmd, CmdDet, Error, Evt, EvtDet, Ini, ParentHandle,
ResourceClass, ResourceClassName, Result, SignSupport, Signer, Ta,
ResourceClass, Result, SignSupport, Signer, Ta,
};
//------------ Rfc8183Id ---------------------------------------------------
@@ -138,11 +138,11 @@ impl<S: Signer> Aggregate for CertAuth<S> {
}
EvtDet::ChildUpdatedResourceClass(child, class, resources) => {
let child = self.children.get_mut(&child).unwrap();
child.set_resources_for_class(&class, resources)
child.set_resources_for_class(class, resources)
}
EvtDet::ChildRemovedResourceClass(child, name) => {
let child = self.children.get_mut(&child).unwrap();
child.remove_resource(name.as_str());
child.remove_resource(&name);
}
//-----------------------------------------------------------------------
@@ -260,7 +260,10 @@ impl<S: Signer> CertAuth<S> {
}
.ok_or_else(|| Error::NotTa)?;
let rc = ta.resources().get("all").ok_or_else(|| Error::NotTa)?;
let rc = ta
.resources()
.get(&ResourceClassName::default())
.ok_or_else(|| Error::NotTa)?;
let cert = rc.current_certificate().ok_or_else(|| Error::NotTa)?;
let resources = cert.resources().clone();
@@ -309,7 +312,7 @@ impl<S: Signer> CertAuth<S> {
/// Gets the resource class by name, if it exists, under any parent
// TODO: Ensure that we have unique resource class names internally
fn resource_class(&self, class_name: &str) -> Option<&ResourceClass> {
fn resource_class(&self, class_name: &ResourceClassName) -> Option<&ResourceClass> {
for parent in self.parents.values() {
if let Some(rc) = parent.resources().get(class_name) {
return Some(rc);
@@ -318,7 +321,7 @@ impl<S: Signer> CertAuth<S> {
None
}
fn resource_class_mut(&mut self, class_name: &str) -> Option<&mut ResourceClass> {
fn resource_class_mut(&mut self, class_name: &ResourceClassName) -> Option<&mut ResourceClass> {
for parent in self.parents.values_mut() {
if let Ok(rc) = parent.class_mut(class_name) {
return Some(rc);
@@ -327,7 +330,7 @@ impl<S: Signer> CertAuth<S> {
None
}
fn get_resource_class(&self, class_name: &str) -> Result<&ResourceClass> {
fn get_resource_class(&self, class_name: &ResourceClassName) -> Result<&ResourceClass> {
self.resource_class(class_name)
.ok_or_else(|| Error::MissingResourceClass)
}
@@ -365,7 +368,7 @@ impl<S: Signer> CertAuth<S> {
pub fn list(&self, child_handle: &Handle) -> Result<api::Entitlements> {
// TODO: Support arbitrary resource classes. See issue #25.
let mut classes = vec![];
if let Some(class) = self.entitlement_class(child_handle, DFLT_CLASS) {
if let Some(class) = self.entitlement_class(child_handle, &ResourceClassName::default()) {
classes.push(class);
}
@@ -377,7 +380,7 @@ impl<S: Signer> CertAuth<S> {
pub fn issuance_response(
&self,
child_handle: &Handle,
class_name: &str,
class_name: &ResourceClassName,
pub_key: &PublicKey,
) -> Result<api::IssuanceResponse> {
let entitlement_class = self
@@ -393,7 +396,7 @@ impl<S: Signer> CertAuth<S> {
fn entitlement_class(
&self,
child_handle: &Handle,
class_name: &str,
class_name: &ResourceClassName,
) -> Option<api::EntitlementClass> {
let child = match self.get_child(child_handle) {
Ok(child) => child,
@@ -424,7 +427,7 @@ impl<S: Signer> CertAuth<S> {
let cert = SigningCert::new(my_rcvd_cert.uri().clone(), my_rcvd_cert.cert().clone());
Some(EntitlementClass::new(
class_name.to_string(),
class_name.clone(),
cert,
child_resources.resources().clone(),
until,
@@ -480,7 +483,7 @@ impl<S: Signer> CertAuth<S> {
fn child_resource_classes_entitlements(
&self,
child_resources: ResourceSet,
) -> Result<HashMap<&ResourceClassName, ResourceSet>> {
) -> Result<HashMap<ResourceClassName, ResourceSet>> {
let mut map = HashMap::new();
let mut matched_resources = ResourceSet::default();
@@ -490,7 +493,7 @@ impl<S: Signer> CertAuth<S> {
let resources = rcvd_cert.resources().intersection(&child_resources);
if !resources.is_empty() {
matched_resources = matched_resources.union(&resources);
map.insert(name, resources);
map.insert(name.clone(), resources);
}
}
}
@@ -577,7 +580,7 @@ impl<S: Signer> CertAuth<S> {
limit: RequestResourceLimit,
signer: &S,
) -> Result<IssuanceResponse> {
let my_rc = self.get_resource_class(class_name.as_str())?;
let my_rc = self.get_resource_class(&class_name)?;
let issuing_key = my_rc.get_current_key()?;
let issuing_cert = issuing_key.incoming_cert();
@@ -664,7 +667,7 @@ impl<S: Signer> CertAuth<S> {
/// for updating child certificates.
pub fn update_published_child_certificates(
&self,
class_name: &str,
class_name: &ResourceClassName,
issued_certs: Vec<&IssuedCert>,
removed_certs: Vec<&Cert>,
signer: Arc<RwLock<S>>,
@@ -860,7 +863,7 @@ impl<S: Signer> CertAuth<S> {
// Determine for each entitlement whether the current is changed, or a new
// resource class can be added.
for (class_name, entitled_resource_set) in child_entitlements.into_iter() {
if match child_resources.remove(class_name) {
if match child_resources.remove(&class_name) {
None => true,
Some(current_resources) => current_resources != &entitled_resource_set,
} {
@@ -868,7 +871,7 @@ impl<S: Signer> CertAuth<S> {
&self.handle,
version,
child_handle.clone(),
class_name.clone(),
class_name,
entitled_resource_set,
));
version += 1;
@@ -902,7 +905,8 @@ impl<S: Signer> CertAuth<S> {
signer: Arc<RwLock<S>>,
) -> ca::Result<Vec<Evt>> {
// verify child and resources
let class_name = request.class_name().to_string();
let class_name = request.class_name().clone();
let child_resources = self
.get_child(&child)?
.resources_for_class(&class_name)
@@ -1075,14 +1079,14 @@ impl<S: Signer> CertAuth<S> {
// from the entitlements. In which case we will have to clean them
// up and un-publish everything there was.
let current_resource_classes = &parent.resources;
let entitled_classes: Vec<&str> = entitlements
let entitled_classes: Vec<&ResourceClassName> = entitlements
.classes()
.iter()
.map(|c| c.class_name())
.collect();
for (name, class) in current_resource_classes
.iter()
.filter(|(name, _class)| !entitled_classes.contains(&name.as_str()))
.filter(|(name, _class)| !entitled_classes.contains(name))
{
let signer = signer.read().unwrap();
@@ -1140,7 +1144,7 @@ impl<S: Signer> CertAuth<S> {
&self.handle,
rc_add_version,
parent_handle.clone(),
name.to_string(),
name.clone(),
rc,
);
@@ -1272,7 +1276,7 @@ impl<S: Signer> CertAuth<S> {
let rc = parent
.resources()
.get(&class_name)
.ok_or_else(|| Error::UnknownResourceClass(class_name.clone()))?;
.ok_or_else(|| Error::unknown_resource_class(&class_name))?;
let finish_details = rc.keyroll_finish(parent_h, class_name, &self.base_repo)?;
@@ -1337,7 +1341,7 @@ impl ParentCa {
let (key, tal) = ta.unpack();
let contact = ParentCaContact::Ta(tal);
let mut resources = HashMap::new();
resources.insert("all".to_string(), ResourceClass::for_ta(key));
resources.insert(ResourceClassName::default(), ResourceClass::for_ta(key));
ParentCa { contact, resources }
}
@@ -1360,13 +1364,13 @@ impl ParentCa {
&self.contact
}
fn class(&self, class_name: &str) -> Result<&ResourceClass> {
fn class(&self, class_name: &ResourceClassName) -> Result<&ResourceClass> {
self.resources
.get(class_name)
.ok_or_else(|| Error::UnknownResourceClass(class_name.to_string()))
}
fn class_mut(&mut self, class_name: &str) -> Result<&mut ResourceClass> {
fn class_mut(&mut self, class_name: &ResourceClassName) -> Result<&mut ResourceClass> {
self.resources
.get_mut(class_name)
.ok_or_else(|| Error::UnknownResourceClass(class_name.to_string()))
+2 -2
View File
@@ -3,12 +3,12 @@ use std::sync::{Arc, RwLock};
use chrono::Duration;
use krill_commons::api::admin::{Handle, ParentCaContact, UpdateChildRequest};
use krill_commons::api::ca::{RcvdCert, ResourceSet};
use krill_commons::api::ca::{RcvdCert, ResourceClassName, ResourceSet};
use krill_commons::api::{Entitlements, IssuanceRequest, RevocationRequest, RevocationResponse};
use krill_commons::eventsourcing;
use krill_commons::remote::id::IdCert;
use crate::ca::{ChildHandle, Evt, ParentHandle, ResourceClassName, Signer};
use crate::ca::{ChildHandle, Evt, ParentHandle, Signer};
//------------ Command -----------------------------------------------------
+4
View File
@@ -89,6 +89,10 @@ impl Error {
pub fn invalid_csr(handle: &Handle, msg: &str) -> Self {
Error::InvalidCsr(handle.clone(), msg.to_string())
}
pub fn unknown_resource_class(class: impl Display) -> Self {
Error::UnknownResourceClass(class.to_string())
}
}
impl std::error::Error for Error {}
+3 -5
View File
@@ -10,8 +10,8 @@ use rpki::x509::{Serial, Time, Validity};
use krill_commons::api::admin::{Handle, ParentCaContact, Token};
use krill_commons::api::ca::{
CertifiedKey, ChildCaDetails, ObjectsDelta, PublicationDelta, RcvdCert, RepoInfo, ResourceSet,
TrustAnchorLocator,
CertifiedKey, ChildCaDetails, ObjectsDelta, PublicationDelta, RcvdCert, RepoInfo,
ResourceClassName, ResourceSet, TrustAnchorLocator,
};
use krill_commons::api::{
IssuanceRequest, IssuanceResponse, RevocationRequest, RevocationResponse,
@@ -21,9 +21,7 @@ use krill_commons::remote::id::IdCert;
use krill_commons::util::softsigner::KeyId;
use crate::ca::signing::Signer;
use crate::ca::{
ChildHandle, Error, ParentHandle, ResourceClass, ResourceClassName, Result, Rfc8183Id,
};
use crate::ca::{ChildHandle, Error, ParentHandle, ResourceClass, Result, Rfc8183Id};
//------------ TaIniDetails --------------------------------------------------
-1
View File
@@ -35,7 +35,6 @@ pub type Result<T> = std::result::Result<T, Error>;
pub type ServerResult<R, S> = std::result::Result<R, ServerError<S>>;
pub type ParentHandle = Handle;
pub type ChildHandle = Handle;
pub type ResourceClassName = String;
pub const TA_NAME: &str = "ta"; // reserved for TA
+16 -15
View File
@@ -3,6 +3,7 @@ use std::ops::Deref;
use std::sync::{Arc, RwLock};
use chrono::Duration;
use serde::{Deserialize, Serialize};
use rpki::crypto::PublicKeyFormat;
use rpki::csr::Csr;
@@ -11,17 +12,16 @@ use rpki::x509::Time;
use krill_commons::api::ca::{
CertifiedKey, CurrentObjects, KeyRef, ObjectsDelta, OldKey, PendingKey, PublicationDelta,
RcvdCert, RepoInfo, ResourceClassInfo, ResourceClassKeysInfo,
RcvdCert, RepoInfo, ResourceClassInfo, ResourceClassKeysInfo, ResourceClassName,
};
use krill_commons::api::{
EntitlementClass, IssuanceRequest, RequestResourceLimit, RevocationRequest,
};
use krill_commons::util::softsigner::KeyId;
use crate::ca::{
self, Error, EvtDet, ParentHandle, ResourceClassName, Result, SignSupport, Signer,
};
use ca::TA_NAME;
use crate::ca::{self, Error, EvtDet, ParentHandle, Result, SignSupport, Signer, TA_NAME};
//------------ ResourceClass -----------------------------------------------
/// A CA may have multiple parents, e.g. two RIRs, and it may not get all its
/// resource entitlements in one set, but in a number of so-called "resource
@@ -650,7 +650,7 @@ impl ResourceClassKeys {
let req = self.create_issuance_req(
base_repo,
name_space,
entitlement.class_name(),
entitlement.class_name().clone(),
key_id,
signer,
)?;
@@ -715,7 +715,7 @@ impl ResourceClassKeys {
&self,
base_repo: &RepoInfo,
name_space: &str,
class_name: &str,
class_name: ResourceClassName,
key: &KeyId,
signer: &S,
) -> Result<IssuanceRequest> {
@@ -733,7 +733,7 @@ impl ResourceClassKeys {
let csr = Csr::decode(enc.as_slice()).map_err(Error::signer)?;
Ok(IssuanceRequest::new(
class_name.to_string(),
class_name,
RequestResourceLimit::default(),
csr,
))
@@ -779,15 +779,16 @@ impl ResourceClassKeys {
.map_err(Error::signer)?
};
let issuance_req =
self.create_issuance_req(base_repo, name_space, &class_name, &key_id, signer)?;
let issuance_req = self.create_issuance_req(
base_repo,
name_space,
class_name.clone(),
&key_id,
signer,
)?;
Ok(vec![
EvtDet::KeyRollPendingKeyAdded(
parent.clone(),
class_name.clone(),
key_id.clone(),
),
EvtDet::KeyRollPendingKeyAdded(parent.clone(), class_name, key_id.clone()),
EvtDet::CertificateRequested(parent, issuance_req, key_id),
])
}
+11 -12
View File
@@ -13,11 +13,10 @@ use krill_commons::api::admin::{
UpdateChildRequest,
};
use krill_commons::api::ca::{
CertAuthList, CertAuthSummary, ChildCaInfo, IssuedCert, RcvdCert, RepoInfo,
CertAuthList, CertAuthSummary, ChildCaInfo, IssuedCert, RcvdCert, RepoInfo, ResourceClassName,
};
use krill_commons::api::{
Entitlements, IssuanceRequest, IssuanceResponse, RevocationRequest, RevocationResponse,
DFLT_CLASS,
};
use krill_commons::eventsourcing::{Aggregate, AggregateStore, DiskAggregateStore};
use krill_commons::remote::builder::SignedMessageBuilder;
@@ -27,8 +26,8 @@ use krill_commons::util::httpclient;
use krill_commons::util::softsigner::KeyId;
use crate::ca::{
self, ta_handle, CertAuth, ChildHandle, CmdDet, IniDet, ParentHandle, ResourceClassName,
ServerError, ServerResult, Signer,
self, ta_handle, CertAuth, ChildHandle, CmdDet, IniDet, ParentHandle, ServerError,
ServerResult, Signer,
};
use crate::mq::EventQueueListener;
@@ -286,7 +285,7 @@ impl<S: Signer> CaServer<S> {
let class_name = issue_req.class_name();
let pub_key = issue_req.csr().public_key();
if class_name != DFLT_CLASS {
if class_name != &ResourceClassName::default() {
unimplemented!("Issue for multiple classes from CAs, issue #25")
}
@@ -603,10 +602,10 @@ impl<S: Signer> CaServer<S> {
) -> ServerResult<Vec<(ResourceClassName, IssuedCert)>, S> {
let mut parent = self.ca_store.get_latest(parent_h)?;
let mut issued_certs: Vec<(String, IssuedCert)> = vec![];
let mut issued_certs: Vec<(ResourceClassName, IssuedCert)> = vec![];
for req in requests.into_iter() {
let class_name = req.class_name().to_string();
let class_name = req.class_name().clone();
let pub_key = req.csr().public_key().clone();
let cmd = CmdDet::child_certify(parent_h, handle.clone(), req, self.signer.clone());
@@ -787,7 +786,7 @@ mod tests {
use ca::EvtDet;
use krill_commons::api::admin::{Handle, ParentCaContact, Token};
use krill_commons::api::ca::{RcvdCert, RepoInfo, ResourceSet};
use krill_commons::api::{IssuanceRequest, DFLT_CLASS};
use krill_commons::api::IssuanceRequest;
use krill_commons::eventsourcing::{Aggregate, AggregateStore, DiskAggregateStore};
use krill_commons::util::softsigner::OpenSslSigner;
use krill_commons::util::test;
@@ -943,7 +942,7 @@ mod tests {
};
let (class_name, limit, csr) = issuance_req.unwrap();
assert_eq!("all", &class_name);
assert_eq!(ResourceClassName::default(), class_name);
assert!(limit.is_empty());
//
@@ -954,7 +953,7 @@ mod tests {
// - Publication
//
let request = IssuanceRequest::new(DFLT_CLASS.to_string(), limit, csr);
let request = IssuanceRequest::new(ResourceClassName::default(), limit, csr);
let ta_cmd =
CmdDet::child_certify(&ta_handle, child_handle.clone(), request, signer.clone());
@@ -970,7 +969,7 @@ mod tests {
let (class_name, _, _, issued) = issuance_res.unwrap();
assert_eq!(child_handle, handle);
assert_eq!(DFLT_CLASS, class_name);
assert_eq!(ResourceClassName::default(), class_name);
//
// --- Return issued certificate to child CA
@@ -984,7 +983,7 @@ mod tests {
let upd_rcvd = CmdDet::upd_received_cert(
&child_handle,
ta_handle,
DFLT_CLASS.to_string(),
ResourceClassName::default(),
rcvd_cert,
signer.clone(),
);
+9 -6
View File
@@ -11,7 +11,7 @@ use krill_commons::api::admin::{
AddChildRequest, AddParentRequest, CertAuthInit, CertAuthPubMode, ChildAuthRequest, Handle,
ParentCaContact, Token, UpdateChildRequest,
};
use krill_commons::api::ca::{CertAuthInfo, ResourceClassKeysInfo, ResourceSet};
use krill_commons::api::ca::{CertAuthInfo, ResourceClassKeysInfo, ResourceClassName, ResourceSet};
use krill_commons::remote::rfc8183;
use krill_commons::util::test;
@@ -192,7 +192,7 @@ pub fn wait_for_new_key(handle: &Handle) {
wait_for(30, "No new key received", move || {
let ca = ca_details(handle);
if let Some(parent) = ca.parent(&ta_handle()) {
if let Some(rc) = parent.resources().get("all") {
if let Some(rc) = parent.resources().get(&ResourceClassName::default()) {
match rc.keys() {
ResourceClassKeysInfo::RollNew(new, _) => {
return new.current_set().number() == 2
@@ -211,7 +211,7 @@ pub fn wait_for_key_roll_complete(handle: &Handle) {
let ca = ca_details(handle);
if let Some(parent) = ca.parent(&ta_handle()) {
if let Some(rc) = parent.resources().get("all") {
if let Some(rc) = parent.resources().get(&ResourceClassName::default()) {
match rc.keys() {
ResourceClassKeysInfo::Active(_) => return true,
_ => return false,
@@ -228,7 +228,10 @@ pub fn wait_for_resource_class_to_disappear(handle: &Handle) {
let ca = ca_details(handle);
if let Some(parent) = ca.parent(&ta_handle()) {
return parent.resources().get("all").is_none();
return parent
.resources()
.get(&ResourceClassName::default())
.is_none();
}
false
@@ -249,7 +252,7 @@ pub fn ta_issued_certs() -> usize {
pub fn ta_issued_resources(child: &Handle) -> ResourceSet {
let ta = ca_details(&ta_handle());
let child = ta.children().get(child).unwrap();
if let Some(resources) = child.resources().get("all") {
if let Some(resources) = child.resources().get(&ResourceClassName::default()) {
if let Some(cert) = resources.certs_iter().next() {
return cert.resource_set().clone(); // for our testing the first will do
}
@@ -261,7 +264,7 @@ pub fn ca_current_resources(handle: &Handle) -> ResourceSet {
let ca = ca_details(handle);
if let Some(parent) = ca.parent(&ta_handle()) {
if let Some(rc) = parent.resources().get("all") {
if let Some(rc) = parent.resources().get(&ResourceClassName::default()) {
match rc.keys() {
ResourceClassKeysInfo::Active(current)
| ResourceClassKeysInfo::RollPending(_, current)