acme/api/order.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
use serde::{Deserialize, Serialize};
use crate::api;
/// The status of an [`api::Authorization`].
///
/// See [RFC 8555 §7.1.3].
///
/// [RFC 8555 §7.1.3]: https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.3
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OrderStatus {
Pending,
Ready,
Processing,
Valid,
Invalid,
}
/// An ACME order object.
///
/// Represents a client's request for a certificate and is used to track the progress of that order
/// through to issuance.
///
/// See [RFC 8555 §7.1.3].
///
/// [RFC 8555 §7.1.3]: https://datatracker.ietf.org/doc/html/rfc8555#section-7.1.3
///
/// # Example JSON
///
/// ```json
/// {
/// "status": "pending",
/// "expires": "2019-01-09T08:26:43.570360537Z",
/// "identifiers": [
/// {
/// "type": "dns",
/// "value": "acmetest.algesten.se"
/// }
/// ],
/// "authorizations": [
/// "https://example.com/acme/authz/YTqpYUthlVfwBncUufE8IRA2TkzZkN4eYWWLMSRqcSs"
/// ],
/// "finalize": "https://example.com/acme/finalize/7738992/18234324"
/// }
/// ```
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Order {
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<OrderStatus>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expires: Option<String>,
pub identifiers: Vec<api::Identifier>,
///
///
/// Uses RFC 3339 format.
pub not_before: Option<String>,
///
///
/// Uses RFC 3339 format.
pub not_after: Option<String>,
pub error: Option<api::Problem>,
pub authorizations: Option<Vec<String>>,
pub finalize: String,
pub certificate: Option<String>,
}
impl Order {
pub(crate) fn from_identifiers(identifiers: Vec<api::Identifier>) -> Self {
Self {
identifiers,
..Default::default()
}
}
/// Returns all domains associated with this order.
pub fn domains(&self) -> Vec<&str> {
self.identifiers
.iter()
.map(|identifier| identifier.value.as_str())
.collect()
}
/// Let's Encrypt was observed to return domains in alternate order which may flip primary with
/// SAN(s).
///
/// This overwrites self without changing the order of the domains.
pub(crate) fn overwrite(&mut self, mut from_api: Self) -> eyre::Result<()> {
// Make sure the lists are the same.
if from_api.identifiers.len() != self.identifiers.len()
|| from_api
.identifiers
.iter()
.any(|id| !self.identifiers.contains(id))
{
return Err(eyre::eyre!(
"Order domain(s) mismatch: had {:?} and got {:?}",
self.identifiers,
from_api.identifiers
));
}
// Then preserve the original order.
from_api.identifiers = std::mem::take(&mut self.identifiers);
*self = from_api;
Ok(())
}
}