use std::{collections::HashMap, fmt};
use bytes::Bytes;
use serde::{Deserialize, Serialize};
use rpki::{
ca::{
idcert::IdCert,
idexchange::{
CaHandle, ChildHandle, ParentHandle, PublisherHandle, RepoInfo,
ServiceUri,
},
provisioning::{
IssuanceRequest, ParentResourceClassName, RequestResourceLimit,
ResourceClassName, RevocationRequest,
},
publication::Base64,
},
crypto::KeyIdentifier,
repository::{
resources::ResourceSet, x509::Time, Cert, Crl, Manifest, Roa,
},
rrdp, uri,
};
use crate::{
commons::ext_serde,
upgrades::{
UpgradeError,
},
};
use crate::api::admin::{
ParentCaContact, ParentServerInfo, PublicationServerInfo,
RepositoryContact,
};
use crate::api::ca::{
CertInfo, IdCertInfo, IssuedCertificate, ObjectName, ReceivedCert,
Revocation, Revocations, RtaName, SuspendedCert, UnsuspendedCert,
};
use crate::api::roa::{RoaInfo, RoaPayloadJsonMapKey};
use crate::api::ta::{TaCertDetails, TrustAnchorLocator};
use crate::server::ca::certauth::Rfc8183Id;
use crate::server::ca::child::ChildCertificateUpdates;
use crate::server::ca::events::CertAuthEvent;
use crate::server::ca::keys::CertifiedKey;
use crate::server::ca::publishing::{
CaObjects, ResourceClassObjects, CurrentKeyState, DeprecatedRepository,
KeyObjectSet, ObjectSetRevision, OldKeyState,
PublishedCrl, PublishedManifest, PublishedObject, ResourceClassKeyState,
StagingKeyState,
};
use crate::server::ca::roa::{RoaAggregateKey, RoaUpdates};
use crate::server::ca::rta::{PreparedRta, SignedRta};
use crate::server::ca::upgrades::pre_0_14_0::aspa::{
Pre0_14_0AspaProvidersUpdate, Pre0_14_0ProviderAs
};
use super::aspa::{Pre0_10_0AspaDefinition, Pre0_10_0AspaObjectsUpdates};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Pre0_10Rfc8183Id {
cert: IdCert,
}
impl From<Pre0_10Rfc8183Id> for Rfc8183Id {
fn from(old: Pre0_10Rfc8183Id) -> Self {
Rfc8183Id::new(old.cert.into())
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldTaCertDetails {
cert: Cert,
resources: ResourceSet,
tal: OldTrustAnchorLocator,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldTrustAnchorLocator {
uris: Vec<uri::Https>,
rsync_uri: Option<uri::Rsync>,
#[serde(
deserialize_with = "ext_serde::de_bytes",
serialize_with = "ext_serde::ser_bytes"
)]
encoded_ski: Bytes,
}
impl TryFrom<OldTaCertDetails> for TaCertDetails {
type Error = UpgradeError;
fn try_from(old: OldTaCertDetails) -> Result<Self, Self::Error> {
let cert = old.cert;
let resources = old.resources;
let tal = old.tal;
let rsync_uri = match tal.rsync_uri {
Some(uri) => uri,
None => {
cert.rpki_manifest()
.ok_or_else(|| {
UpgradeError::custom(
"Cannot migrate TA, rsync URI is missing and TA cert does not have a manifest URI?!",
)
})?
.parent()
.unwrap()
.join(b"ta.cer")
.unwrap()
}
};
let limit = RequestResourceLimit::default();
let public_key = cert.subject_public_key_info().clone();
let rvcd_cert =
ReceivedCert::create(cert, rsync_uri.clone(), resources, limit)
.map_err(|e| {
UpgradeError::Custom(format!(
"Could not convert old TA details: {e}"
))
})?;
let tal = TrustAnchorLocator::new(tal.uris, rsync_uri, &public_key);
Ok(TaCertDetails { cert: rvcd_cert, tal })
}
}
impl PartialEq for OldTaCertDetails {
fn eq(&self, other: &Self) -> bool {
self.tal == other.tal
&& self.resources == other.resources
&& self.cert.to_captured().as_slice()
== other.cert.to_captured().as_slice()
}
}
impl Eq for OldTaCertDetails {}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldChildCertificateUpdates {
#[serde(skip_serializing_if = "Vec::is_empty", default)]
issued: Vec<OldDelegatedCertificate>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
removed: Vec<KeyIdentifier>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
suspended: Vec<OldSuspendedCert>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
unsuspended: Vec<OldUnsuspendedCert>,
}
impl TryFrom<OldChildCertificateUpdates> for ChildCertificateUpdates {
type Error = UpgradeError;
fn try_from(
old: OldChildCertificateUpdates,
) -> Result<Self, UpgradeError> {
let mut issued: Vec<IssuedCertificate> = vec![];
let mut suspended: Vec<SuspendedCert> = vec![];
let mut unsuspended: Vec<UnsuspendedCert> = vec![];
for old_delegated in old.issued.into_iter() {
issued.push(old_delegated.try_into()?);
}
for old_suspended in old.suspended.into_iter() {
suspended.push(old_suspended.try_into()?);
}
for old_unsuspended in old.unsuspended.into_iter() {
unsuspended.push(old_unsuspended.try_into()?);
}
Ok(ChildCertificateUpdates {
issued,
removed: old.removed,
suspended,
unsuspended,
})
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldDelegatedCertificate {
uri: uri::Rsync, limit: RequestResourceLimit, resource_set: ResourceSet,
cert: Cert,
}
impl PartialEq for OldDelegatedCertificate {
fn eq(&self, other: &OldDelegatedCertificate) -> bool {
self.uri == other.uri
&& self.limit == other.limit
&& self.resource_set == other.resource_set
&& self.cert.to_captured().as_slice()
== other.cert.to_captured().as_slice()
}
}
impl Eq for OldDelegatedCertificate {}
pub type OldSuspendedCert = OldDelegatedCertificate;
pub type OldUnsuspendedCert = OldDelegatedCertificate;
impl<T> TryFrom<OldDelegatedCertificate> for CertInfo<T> {
type Error = UpgradeError;
fn try_from(old: OldDelegatedCertificate) -> Result<Self, Self::Error> {
CertInfo::create(old.cert, old.uri, old.resource_set, old.limit)
.map_err(|e| {
UpgradeError::Custom(format!(
"cannot convert certificate: {e}"
))
})
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldRcvdCert {
cert: Cert,
uri: uri::Rsync,
resources: ResourceSet,
}
impl PartialEq for OldRcvdCert {
fn eq(&self, other: &OldRcvdCert) -> bool {
self.cert.to_captured().into_bytes()
== other.cert.to_captured().into_bytes()
&& self.uri == other.uri
}
}
impl Eq for OldRcvdCert {}
impl TryFrom<OldRcvdCert> for ReceivedCert {
type Error = UpgradeError;
fn try_from(old: OldRcvdCert) -> Result<Self, Self::Error> {
ReceivedCert::create(
old.cert,
old.uri,
old.resources,
RequestResourceLimit::default(),
)
.map_err(|e| {
UpgradeError::Custom(format!("cannot convert certificate: {e}"))
})
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldCertifiedKey {
key_id: KeyIdentifier,
incoming_cert: OldRcvdCert,
request: Option<IssuanceRequest>,
#[serde(skip_serializing_if = "Option::is_none")]
old_repo: Option<RepoInfo>,
}
impl TryFrom<OldCertifiedKey> for CertifiedKey {
type Error = UpgradeError;
fn try_from(old: OldCertifiedKey) -> Result<Self, Self::Error> {
Ok(CertifiedKey::new(
old.key_id,
old.incoming_cert.try_into()?,
old.request,
old.old_repo,
))
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[allow(clippy::large_enum_variant)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type")]
pub enum OldParentCaContact {
Ta(OldTaCertDetails),
Rfc6492(OldParentResponse),
}
impl TryFrom<OldParentCaContact> for ParentCaContact {
type Error = UpgradeError;
fn try_from(old: OldParentCaContact) -> Result<Self, Self::Error> {
match old {
OldParentCaContact::Ta(_old) => Err(UpgradeError::OldTaMigration),
OldParentCaContact::Rfc6492(old) => {
Ok(ParentCaContact::Rfc6492(old.into()))
}
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldParentResponse {
id_cert: IdCert,
parent_handle: ParentHandle,
child_handle: ChildHandle,
service_uri: ServiceUri,
tag: Option<String>,
}
impl From<OldParentResponse> for ParentServerInfo {
fn from(old: OldParentResponse) -> Self {
let id_cert_info = IdCertInfo::from(&old.id_cert);
ParentServerInfo {
service_uri: old.service_uri,
parent_handle: old.parent_handle,
child_handle: old.child_handle,
id_cert: id_cert_info,
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[allow(clippy::large_enum_variant)]
pub struct OldRepositoryContact {
repository_response: OldRepositoryResponse,
}
impl From<OldRepositoryContact> for RepositoryContact {
fn from(old: OldRepositoryContact) -> Self {
RepositoryContact {
repo_info: old.repository_response.repo_info,
server_info: PublicationServerInfo {
public_key:
old.repository_response.id_cert.public_key().clone(),
service_uri: old.repository_response.service_uri,
}
}
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldRoaInfo {
roa: Roa,
since: Time, }
impl PartialEq for OldRoaInfo {
fn eq(&self, other: &Self) -> bool {
self.roa.to_captured().as_slice()
== other.roa.to_captured().as_slice()
}
}
impl Eq for OldRoaInfo {}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldAggregateRoaInfo {
authorizations: Vec<RoaPayloadJsonMapKey>,
#[serde(flatten)]
roa: OldRoaInfo,
}
impl From<OldAggregateRoaInfo> for RoaInfo {
fn from(old: OldAggregateRoaInfo) -> Self {
RoaInfo::new(old.authorizations, old.roa.roa)
}
}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldRoaUpdates {
#[serde(
skip_serializing_if = "HashMap::is_empty",
default = "HashMap::new",
with = "updated_sorted_map"
)]
updated: HashMap<RoaPayloadJsonMapKey, OldRoaInfo>,
#[serde(
skip_serializing_if = "HashMap::is_empty",
default = "HashMap::new",
with = "removed_sorted_map"
)]
removed: HashMap<RoaPayloadJsonMapKey, OldRevokedObject>,
#[serde(
skip_serializing_if = "HashMap::is_empty",
default = "HashMap::new",
with = "aggregate_updated_sorted_map"
)]
aggregate_updated: HashMap<RoaAggregateKey, OldAggregateRoaInfo>,
#[serde(
skip_serializing_if = "HashMap::is_empty",
default = "HashMap::new",
with = "aggregate_removed_sorted_map"
)]
aggregate_removed: HashMap<RoaAggregateKey, OldRevokedObject>,
}
impl From<OldRoaUpdates> for RoaUpdates {
fn from(old: OldRoaUpdates) -> Self {
let updated: HashMap<RoaPayloadJsonMapKey, RoaInfo> = old
.updated
.into_iter()
.map(|(auth, old_info)| {
(auth, RoaInfo::new(vec![auth], old_info.roa))
})
.collect();
let aggregate_updated: HashMap<RoaAggregateKey, RoaInfo> = old
.aggregate_updated
.into_iter()
.map(|(auth, old_info)| (auth, old_info.into()))
.collect();
let removed = old.removed.into_keys().collect();
let aggregate_removed = old.aggregate_removed.into_keys().collect();
RoaUpdates::new(
updated,
removed,
aggregate_updated,
aggregate_removed,
)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldRevokedObject {
revocation: Revocation,
hash: rrdp::Hash,
}
mod updated_sorted_map {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct Item {
auth: RoaPayloadJsonMapKey,
roa: OldRoaInfo,
}
#[derive(Debug, Serialize)]
struct ItemRef<'a> {
auth: &'a RoaPayloadJsonMapKey,
roa: &'a OldRoaInfo,
}
pub fn serialize<S>(
map: &HashMap<RoaPayloadJsonMapKey, OldRoaInfo>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut sorted_vec: Vec<ItemRef> = map
.iter()
.map(|(auth, roa)| ItemRef { auth, roa })
.collect();
sorted_vec.sort_by_key(|el| el.auth);
serializer.collect_seq(sorted_vec)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<RoaPayloadJsonMapKey, OldRoaInfo>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<Item>::deserialize(deserializer)? {
map.insert(item.auth, item.roa);
}
Ok(map)
}
}
mod aggregate_updated_sorted_map {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct Item {
agg: RoaAggregateKey,
roa: OldAggregateRoaInfo,
}
#[derive(Debug, Serialize)]
struct ItemRef<'a> {
agg: &'a RoaAggregateKey,
roa: &'a OldAggregateRoaInfo,
}
pub fn serialize<S>(
map: &HashMap<RoaAggregateKey, OldAggregateRoaInfo>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut sorted_vec: Vec<ItemRef> =
map.iter().map(|(agg, roa)| ItemRef { agg, roa }).collect();
sorted_vec.sort_by_key(|el| el.agg);
serializer.collect_seq(sorted_vec)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<RoaAggregateKey, OldAggregateRoaInfo>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<Item>::deserialize(deserializer)? {
map.insert(item.agg, item.roa);
}
Ok(map)
}
}
mod removed_sorted_map {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct Item {
auth: RoaPayloadJsonMapKey,
removed: OldRevokedObject,
}
#[derive(Debug, Serialize)]
struct ItemRef<'a> {
auth: &'a RoaPayloadJsonMapKey,
removed: &'a OldRevokedObject,
}
pub fn serialize<S>(
map: &HashMap<RoaPayloadJsonMapKey, OldRevokedObject>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut sorted_vec: Vec<ItemRef> = map
.iter()
.map(|(auth, removed)| ItemRef { auth, removed })
.collect();
sorted_vec.sort_by_key(|el| el.auth);
serializer.collect_seq(sorted_vec)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<RoaPayloadJsonMapKey, OldRevokedObject>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<Item>::deserialize(deserializer)? {
map.insert(item.auth, item.removed);
}
Ok(map)
}
}
mod aggregate_removed_sorted_map {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct Item {
agg: RoaAggregateKey,
removed: OldRevokedObject,
}
#[derive(Debug, Serialize)]
struct ItemRef<'a> {
agg: &'a RoaAggregateKey,
removed: &'a OldRevokedObject,
}
pub fn serialize<S>(
map: &HashMap<RoaAggregateKey, OldRevokedObject>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut sorted_vec: Vec<ItemRef> = map
.iter()
.map(|(agg, removed)| ItemRef { agg, removed })
.collect();
sorted_vec.sort_by_key(|el| el.agg);
serializer.collect_seq(sorted_vec)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<RoaAggregateKey, OldRevokedObject>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<Item>::deserialize(deserializer)? {
map.insert(item.agg, item.removed);
}
Ok(map)
}
}
#[derive(Clone, Debug, Deserialize, Eq, Serialize, PartialEq)]
pub struct OldRepositoryResponse {
id_cert: IdCert,
publisher_handle: PublisherHandle,
service_uri: ServiceUri,
repo_info: RepoInfo,
tag: Option<String>,
}
pub type Pre0_10CertAuthInitEvent = Pre0_10CaIniDet;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Pre0_10CaIniDet {
id: Pre0_10Rfc8183Id,
}
impl From<Pre0_10CaIniDet> for Rfc8183Id {
fn from(old: Pre0_10CaIniDet) -> Self {
old.id.into()
}
}
impl fmt::Display for Pre0_10CaIniDet {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Initialized with ID key hash: {}",
self.id.cert.public_key().key_identifier()
)?;
Ok(())
}
}
pub type Pre0_10CertAuthEvent = Pre0_10CertAuthEventDetails;
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[allow(clippy::large_enum_variant)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type")]
pub enum Pre0_10CertAuthEventDetails {
TrustAnchorMade {
ta_cert_details: OldTaCertDetails,
},
ChildAdded {
child: ChildHandle,
id_cert: IdCert,
resources: ResourceSet,
},
ChildCertificateIssued {
child: ChildHandle,
resource_class_name: ResourceClassName,
ki: KeyIdentifier,
},
ChildKeyRevoked {
child: ChildHandle,
resource_class_name: ResourceClassName,
ki: KeyIdentifier,
},
ChildCertificatesUpdated {
resource_class_name: ResourceClassName,
updates: OldChildCertificateUpdates,
},
ChildUpdatedIdCert {
child: ChildHandle,
id_cert: IdCert,
},
ChildUpdatedResources {
child: ChildHandle,
resources: ResourceSet,
},
ChildRemoved {
child: ChildHandle,
},
ChildSuspended {
child: ChildHandle,
},
ChildUnsuspended {
child: ChildHandle,
},
IdUpdated {
id: Pre0_10Rfc8183Id,
},
ParentAdded {
parent: ParentHandle,
contact: OldParentCaContact,
},
ParentUpdated {
parent: ParentHandle,
contact: OldParentCaContact,
},
ParentRemoved {
parent: ParentHandle,
},
ResourceClassAdded {
resource_class_name: ResourceClassName,
parent: ParentHandle,
parent_resource_class_name: ParentResourceClassName,
pending_key: KeyIdentifier,
},
ResourceClassRemoved {
resource_class_name: ResourceClassName,
parent: ParentHandle,
revoke_requests: Vec<RevocationRequest>,
},
CertificateRequested {
resource_class_name: ResourceClassName,
req: IssuanceRequest,
ki: KeyIdentifier, },
CertificateReceived {
resource_class_name: ResourceClassName,
rcvd_cert: OldRcvdCert,
ki: KeyIdentifier, },
KeyRollPendingKeyAdded {
resource_class_name: ResourceClassName,
pending_key_id: KeyIdentifier,
},
KeyPendingToNew {
resource_class_name: ResourceClassName,
new_key: OldCertifiedKey,
},
KeyPendingToActive {
resource_class_name: ResourceClassName,
current_key: OldCertifiedKey,
},
KeyRollActivated {
resource_class_name: ResourceClassName,
revoke_req: RevocationRequest,
},
KeyRollFinished {
resource_class_name: ResourceClassName,
},
UnexpectedKeyFound {
resource_class_name: ResourceClassName,
revoke_req: RevocationRequest,
},
RouteAuthorizationAdded {
auth: RoaPayloadJsonMapKey,
},
RouteAuthorizationRemoved {
auth: RoaPayloadJsonMapKey,
},
RoasUpdated {
resource_class_name: ResourceClassName,
updates: OldRoaUpdates,
},
AspaConfigAdded {
aspa_config: Pre0_10_0AspaDefinition,
},
AspaConfigUpdated {
customer: Pre0_14_0ProviderAs,
update: Pre0_14_0AspaProvidersUpdate,
},
AspaConfigRemoved {
customer: Pre0_14_0ProviderAs,
},
AspaObjectsUpdated {
resource_class_name: ResourceClassName,
updates: Pre0_10_0AspaObjectsUpdates,
},
RepoUpdated {
contact: OldRepositoryContact,
},
RtaSigned {
name: RtaName,
rta: SignedRta,
},
RtaPrepared {
name: RtaName,
prepared: PreparedRta,
},
}
impl TryFrom<Pre0_10CertAuthEventDetails> for CertAuthEvent {
type Error = UpgradeError;
fn try_from(
old: Pre0_10CertAuthEventDetails,
) -> Result<Self, Self::Error> {
Ok(match old {
Pre0_10CertAuthEventDetails::TrustAnchorMade { .. } => {
return Err(UpgradeError::OldTaMigration)
}
Pre0_10CertAuthEventDetails::ChildAdded {
child,
id_cert,
resources,
} => CertAuthEvent::ChildAdded {
child,
id_cert: id_cert.into(),
resources,
},
Pre0_10CertAuthEventDetails::ChildCertificateIssued {
child,
resource_class_name,
ki,
} => CertAuthEvent::ChildCertificateIssued {
child,
resource_class_name,
ki,
},
Pre0_10CertAuthEventDetails::ChildKeyRevoked {
child,
resource_class_name,
ki,
} => CertAuthEvent::ChildKeyRevoked {
child,
resource_class_name,
ki,
},
Pre0_10CertAuthEventDetails::ChildCertificatesUpdated {
resource_class_name,
updates,
} => CertAuthEvent::ChildCertificatesUpdated {
resource_class_name,
updates: updates.try_into()?,
},
Pre0_10CertAuthEventDetails::ChildUpdatedIdCert {
child,
id_cert,
} => CertAuthEvent::ChildUpdatedIdCert {
child,
id_cert: id_cert.into(),
},
Pre0_10CertAuthEventDetails::ChildUpdatedResources {
child,
resources,
} => CertAuthEvent::ChildUpdatedResources { child, resources },
Pre0_10CertAuthEventDetails::ChildRemoved { child } => {
CertAuthEvent::ChildRemoved { child }
}
Pre0_10CertAuthEventDetails::ChildSuspended { child } => {
CertAuthEvent::ChildSuspended { child }
}
Pre0_10CertAuthEventDetails::ChildUnsuspended { child } => {
CertAuthEvent::ChildUnsuspended { child }
}
Pre0_10CertAuthEventDetails::IdUpdated { id } => {
CertAuthEvent::IdUpdated { id: id.into() }
}
Pre0_10CertAuthEventDetails::ParentAdded { parent, contact } => {
CertAuthEvent::ParentAdded {
parent,
contact: contact.try_into()?,
}
}
Pre0_10CertAuthEventDetails::ParentUpdated {
parent,
contact,
} => CertAuthEvent::ParentUpdated {
parent,
contact: contact.try_into()?,
},
Pre0_10CertAuthEventDetails::ParentRemoved { parent } => {
CertAuthEvent::ParentRemoved { parent }
}
Pre0_10CertAuthEventDetails::ResourceClassAdded {
resource_class_name,
parent,
parent_resource_class_name,
pending_key,
} => CertAuthEvent::ResourceClassAdded {
resource_class_name,
parent,
parent_resource_class_name,
pending_key,
},
Pre0_10CertAuthEventDetails::ResourceClassRemoved {
resource_class_name,
parent,
revoke_requests,
} => CertAuthEvent::ResourceClassRemoved {
resource_class_name,
parent,
revoke_requests,
},
Pre0_10CertAuthEventDetails::CertificateRequested {
resource_class_name,
req,
ki,
} => CertAuthEvent::CertificateRequested {
resource_class_name,
req,
ki,
},
Pre0_10CertAuthEventDetails::CertificateReceived {
resource_class_name,
rcvd_cert,
ki,
} => CertAuthEvent::CertificateReceived {
resource_class_name,
rcvd_cert: rcvd_cert.try_into()?,
ki,
},
Pre0_10CertAuthEventDetails::KeyRollPendingKeyAdded {
resource_class_name,
pending_key_id,
} => CertAuthEvent::KeyRollPendingKeyAdded {
resource_class_name,
pending_key_id,
},
Pre0_10CertAuthEventDetails::KeyPendingToNew {
resource_class_name,
new_key,
} => CertAuthEvent::KeyPendingToNew {
resource_class_name,
new_key: new_key.try_into()?,
},
Pre0_10CertAuthEventDetails::KeyPendingToActive {
resource_class_name,
current_key,
} => CertAuthEvent::KeyPendingToActive {
resource_class_name,
current_key: current_key.try_into()?,
},
Pre0_10CertAuthEventDetails::KeyRollActivated {
resource_class_name,
revoke_req,
} => CertAuthEvent::KeyRollActivated {
resource_class_name,
revoke_req,
},
Pre0_10CertAuthEventDetails::KeyRollFinished {
resource_class_name,
} => CertAuthEvent::KeyRollFinished {
resource_class_name,
},
Pre0_10CertAuthEventDetails::UnexpectedKeyFound {
resource_class_name,
revoke_req,
} => CertAuthEvent::UnexpectedKeyFound {
resource_class_name,
revoke_req,
},
Pre0_10CertAuthEventDetails::RouteAuthorizationAdded { auth } => {
CertAuthEvent::RouteAuthorizationAdded { auth }
}
Pre0_10CertAuthEventDetails::RouteAuthorizationRemoved {
auth,
} => CertAuthEvent::RouteAuthorizationRemoved { auth },
Pre0_10CertAuthEventDetails::RoasUpdated {
resource_class_name,
updates,
} => CertAuthEvent::RoasUpdated {
resource_class_name,
updates: updates.into(),
},
Pre0_10CertAuthEventDetails::AspaConfigAdded { .. } => {
unimplemented!("not migrated")
}
Pre0_10CertAuthEventDetails::AspaConfigUpdated { .. } => {
unimplemented!("not migrated")
}
Pre0_10CertAuthEventDetails::AspaConfigRemoved { .. } => {
unimplemented!("not migrated")
}
Pre0_10CertAuthEventDetails::AspaObjectsUpdated { .. } => {
unimplemented!("not migrated")
}
Pre0_10CertAuthEventDetails::RepoUpdated { contact } => {
CertAuthEvent::RepoUpdated {
contact: contact.into(),
}
}
Pre0_10CertAuthEventDetails::RtaSigned { name, rta } => {
CertAuthEvent::RtaSigned { name, rta }
}
Pre0_10CertAuthEventDetails::RtaPrepared { name, prepared } => {
CertAuthEvent::RtaPrepared { name, prepared }
}
})
}
}
impl fmt::Display for Pre0_10CertAuthEventDetails {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
unimplemented!("not used for migration")
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldCaObjects {
ca: CaHandle,
repo: Option<OldRepositoryContact>,
#[serde(with = "old_ca_objects_classes_serde")]
classes: HashMap<ResourceClassName, OldResourceClassObjects>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
deprecated_repos: Vec<OldDeprecatedRepository>,
}
impl TryFrom<OldCaObjects> for CaObjects {
type Error = UpgradeError;
fn try_from(old: OldCaObjects) -> Result<Self, Self::Error> {
let ca = old.ca;
let repo = old.repo.map(|contact| contact.into());
let mut classes: HashMap<
ResourceClassName,
ResourceClassObjects,
> = HashMap::new();
for (rcn, old_objects) in old.classes.into_iter() {
classes.insert(rcn, old_objects.try_into()?);
}
let deprecated_repos = old
.deprecated_repos
.into_iter()
.map(|deprecated| deprecated.into())
.collect();
Ok(CaObjects::from_parts(ca, repo, classes, deprecated_repos))
}
}
mod old_ca_objects_classes_serde {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct ClassesItem {
class_name: ResourceClassName,
objects: OldResourceClassObjects,
}
#[derive(Debug, Serialize)]
struct ClassesItemRef<'a> {
class_name: &'a ResourceClassName,
objects: &'a OldResourceClassObjects,
}
pub fn serialize<S>(
map: &HashMap<ResourceClassName, OldResourceClassObjects>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(map.iter().map(|(class_name, objects)| {
ClassesItemRef {
class_name,
objects,
}
}))
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<ResourceClassName, OldResourceClassObjects>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<ClassesItem>::deserialize(deserializer)? {
map.insert(item.class_name, item.objects);
}
Ok(map)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldDeprecatedRepository {
contact: OldRepositoryContact,
clean_attempts: usize,
}
impl From<OldDeprecatedRepository> for DeprecatedRepository {
fn from(old: OldDeprecatedRepository) -> Self {
DeprecatedRepository::new(old.contact.into(), old.clean_attempts)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldResourceClassObjects {
keys: OldResourceClassKeyState,
}
impl TryFrom<OldResourceClassObjects> for ResourceClassObjects {
type Error = UpgradeError;
fn try_from(old: OldResourceClassObjects) -> Result<Self, Self::Error> {
old.keys.try_into().map(ResourceClassObjects::new)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum OldResourceClassKeyState {
Current(OldCurrentKeyState),
Staging(OldStagingKeyState),
Old(OldOldKeyState),
}
impl TryFrom<OldResourceClassKeyState> for ResourceClassKeyState {
type Error = UpgradeError;
fn try_from(old: OldResourceClassKeyState) -> Result<Self, Self::Error> {
Ok(match old {
OldResourceClassKeyState::Current(state) => {
ResourceClassKeyState::Current(state.try_into()?)
}
OldResourceClassKeyState::Staging(state) => {
ResourceClassKeyState::Staging(state.try_into()?)
}
OldResourceClassKeyState::Old(state) => {
ResourceClassKeyState::Old(state.try_into()?)
}
})
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldCurrentKeyState {
current_set: OldCurrentKeyObjectSet,
}
impl TryFrom<OldCurrentKeyState> for CurrentKeyState {
type Error = UpgradeError;
fn try_from(old: OldCurrentKeyState) -> Result<Self, Self::Error> {
Ok(CurrentKeyState::new(old.current_set.try_into()?))
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldStagingKeyState {
staging_set: OldBasicKeyObjectSet,
current_set: OldCurrentKeyObjectSet,
}
impl TryFrom<OldStagingKeyState> for StagingKeyState {
type Error = UpgradeError;
fn try_from(old: OldStagingKeyState) -> Result<Self, Self::Error> {
Ok(StagingKeyState::new(
old.staging_set.try_into()?,
old.current_set.try_into()?,
))
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldOldKeyState {
current_set: OldCurrentKeyObjectSet,
old_set: OldBasicKeyObjectSet,
}
impl TryFrom<OldOldKeyState> for OldKeyState {
type Error = UpgradeError;
fn try_from(old: OldOldKeyState) -> Result<Self, Self::Error> {
Ok(OldKeyState::new(
old.current_set.try_into()?,
old.old_set.try_into()?,
))
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldCurrentKeyObjectSet {
#[serde(flatten)]
basic: OldBasicKeyObjectSet,
#[serde(with = "objects_to_roas_serde")]
roas: HashMap<ObjectName, OldPublishedRoa>,
#[serde(with = "objects_to_certs_serde")]
certs: HashMap<ObjectName, OldPublishedCert>,
}
impl TryFrom<OldCurrentKeyObjectSet> for KeyObjectSet {
type Error = UpgradeError;
fn try_from(old: OldCurrentKeyObjectSet) -> Result<Self, Self::Error> {
let signing_cert = old.basic.signing_cert.try_into()?;
let number = old.basic.number;
let this_update = old.basic.manifest.this_update();
let next_update = old.basic.manifest.next_update();
let revision =
ObjectSetRevision::new(number, this_update, next_update);
let revocations = old.basic.revocations;
let manifest = old.basic.manifest.into();
let crl = old.basic.crl.into();
let old_repo = old.basic.old_repo.map(|repo| repo.into());
let mut published_objects = HashMap::new();
for (name, old_roa) in old.roas.into_iter() {
let base64 = Base64::from(&old_roa.0);
let serial = old_roa.0.cert().serial_number();
let expires = old_roa.0.cert().validity().not_after();
let published_object =
PublishedObject::new(name.clone(), base64, serial, expires);
published_objects.insert(name, published_object);
}
for (name, old_cert) in old.certs.into_iter() {
let base64 = Base64::from(&old_cert.cert);
let serial = old_cert.cert.serial_number();
let expires = old_cert.cert.validity().not_after();
let published_object =
PublishedObject::new(name.clone(), base64, serial, expires);
published_objects.insert(name, published_object);
}
Ok(KeyObjectSet::new(
signing_cert,
revision,
revocations,
manifest,
crl,
published_objects,
old_repo,
))
}
}
mod objects_to_roas_serde {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct NameRoaItem {
name: ObjectName,
roa: OldPublishedRoa,
}
#[derive(Debug, Serialize)]
struct NameRoaItemRef<'a> {
name: &'a ObjectName,
roa: &'a OldPublishedRoa,
}
pub fn serialize<S>(
map: &HashMap<ObjectName, OldPublishedRoa>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(
map.iter().map(|(name, roa)| NameRoaItemRef { name, roa }),
)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<ObjectName, OldPublishedRoa>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<NameRoaItem>::deserialize(deserializer)? {
map.insert(item.name, item.roa);
}
Ok(map)
}
}
mod objects_to_certs_serde {
use super::*;
use serde::de::{Deserialize, Deserializer};
use serde::ser::Serializer;
#[derive(Debug, Deserialize)]
struct NameCertItem {
name: ObjectName,
issued: OldPublishedCert,
}
#[derive(Debug, Serialize)]
struct NameCertItemRef<'a> {
name: &'a ObjectName,
issued: &'a OldPublishedCert,
}
pub fn serialize<S>(
map: &HashMap<ObjectName, OldPublishedCert>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(
map.iter()
.map(|(name, issued)| NameCertItemRef { name, issued }),
)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<ObjectName, OldPublishedCert>, D::Error>
where
D: Deserializer<'de>,
{
let mut map = HashMap::new();
for item in Vec::<NameCertItem>::deserialize(deserializer)? {
map.insert(item.name, item.issued);
}
Ok(map)
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct OldBasicKeyObjectSet {
signing_cert: OldRcvdCert,
number: u64,
revocations: Revocations,
manifest: OldPublishedManifest,
crl: OldPublishedCrl,
#[serde(skip_serializing_if = "Option::is_none")]
old_repo: Option<OldRepositoryContact>,
}
impl TryFrom<OldBasicKeyObjectSet> for KeyObjectSet {
type Error = UpgradeError;
fn try_from(old: OldBasicKeyObjectSet) -> Result<Self, Self::Error> {
let signing_cert = old.signing_cert.try_into()?;
let number = old.number;
let this_update = old.manifest.this_update();
let next_update = old.manifest.next_update();
let revision =
ObjectSetRevision::new(number, this_update, next_update);
let revocations = old.revocations;
let manifest = old.manifest.into();
let crl = old.crl.into();
let empty_object_set = HashMap::new();
let old_repo = old.old_repo.map(|repo| repo.into());
Ok(KeyObjectSet::new(
signing_cert,
revision,
revocations,
manifest,
crl,
empty_object_set,
old_repo,
))
}
}
pub type OldPublishedCert = OldDelegatedCertificate;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldPublishedRoa(Roa);
impl PartialEq for OldPublishedRoa {
fn eq(&self, other: &Self) -> bool {
self.0.to_captured().into_bytes()
== other.0.to_captured().into_bytes()
}
}
impl Eq for OldPublishedRoa {}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldPublishedManifest(Manifest);
impl OldPublishedManifest {
pub fn this_update(&self) -> Time {
self.0.this_update()
}
pub fn next_update(&self) -> Time {
self.0.next_update()
}
}
impl From<OldPublishedManifest> for PublishedManifest {
fn from(old: OldPublishedManifest) -> Self {
old.0.into()
}
}
impl PartialEq for OldPublishedManifest {
fn eq(&self, other: &Self) -> bool {
self.0.to_captured().into_bytes()
== other.0.to_captured().into_bytes()
}
}
impl Eq for OldPublishedManifest {}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OldPublishedCrl(Crl);
impl From<OldPublishedCrl> for PublishedCrl {
fn from(old: OldPublishedCrl) -> Self {
old.0.into()
}
}
impl PartialEq for OldPublishedCrl {
fn eq(&self, other: &Self) -> bool {
self.0.to_captured().into_bytes()
== other.0.to_captured().into_bytes()
}
}
impl Eq for OldPublishedCrl {}