acme_proxy_core/identifier.rs
1//! The ACME identifier (RFC 8555 §7.1.4) — the name an order, an
2//! authorization, a filter check and a signer's CSR check all speak about.
3//!
4//! Its own module rather than beside the order row it is stored in, because
5//! everything above the storage layer names it too: the problem documents'
6//! `subproblems`, the filters, the audit trail's frozen identifier list.
7
8use serde::{Deserialize, Serialize};
9
10/// An ACME identifier (RFC 8555 §7.1.4). Only `dns` is supported here, but the
11/// type is kept generic so the JSON round-trips whatever a client sent.
12///
13/// Stored inside the order's `identifiers` JSON array and echoed verbatim in the
14/// order object. Reused by the signer to check a finalize CSR's SANs.
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct Identifier {
17 #[serde(rename = "type")]
18 pub typ: String,
19 pub value: String,
20}
21
22impl Identifier {
23 /// A `dns` identifier, which is every identifier this server issues for.
24 ///
25 /// Here rather than in a test helper because the struct had no constructor
26 /// at all, and twelve modules had each grown their own `fn dns(&str)` to
27 /// avoid writing the literal — the same accumulation that put `TempDir` in
28 /// `testutil`, except these are one line each and belong in production,
29 /// where the handlers building identifiers benefit too.
30 #[must_use]
31 pub fn dns(value: impl Into<String>) -> Self {
32 Self::new("dns", value)
33 }
34
35 /// An identifier of any type. `typ` is kept a free string because RFC 8555
36 /// §9.7.7 leaves the registry open and the order object echoes back
37 /// whatever a client sent.
38 #[must_use]
39 pub fn new(typ: impl Into<String>, value: impl Into<String>) -> Self {
40 Self {
41 typ: typ.into(),
42 value: value.into(),
43 }
44 }
45}