Some documentation

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-05-04 11:04:17 +02:00
parent 7c67886e1f
commit 47af324d94

View File

@ -1,3 +1,8 @@
//! ACME Account management and creation. The [`Account`] type also contains most of the ACME API
//! entry point helpers.
#![deny(missing_docs)]
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryFrom; use std::convert::TryFrom;
@ -14,6 +19,12 @@ use crate::order::{NewOrder, Order, OrderData};
use crate::request::Request; use crate::request::Request;
use crate::Error; use crate::Error;
/// An ACME Account.
///
/// This contains the location URL, the account data and the private key for an account.
/// This can directly be serialized via serde to persist the account.
///
/// In order to register a new account with an ACME provider, see the [`Account::creator`] method.
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Account { pub struct Account {
@ -28,6 +39,7 @@ pub struct Account {
} }
impl Account { impl Account {
/// Rebuild an account from its components.
pub fn from_parts(location: String, private_key: String, data: AccountData) -> Self { pub fn from_parts(location: String, private_key: String, data: AccountData) -> Self {
Self { Self {
location, location,
@ -36,10 +48,15 @@ impl Account {
} }
} }
/// Builds an [`AccountCreator`]. This handles creation of the private key and account data as
/// well as handling the response sent by the server for the registration request.
pub fn creator() -> AccountCreator { pub fn creator() -> AccountCreator {
AccountCreator::default() AccountCreator::default()
} }
/// Place a new order. This will build a [`NewOrder`] representing an in flight order creation
/// request.
///
/// The returned `NewOrder`'s `request` option is *guaranteed* to be `Some(Request)`. /// The returned `NewOrder`'s `request` option is *guaranteed* to be `Some(Request)`.
pub fn new_order( pub fn new_order(
&self, &self,
@ -73,7 +90,7 @@ impl Account {
Ok(NewOrder::new(request)) Ok(NewOrder::new(request))
} }
/// Prepare a "POST-as-GET" request to fetch data. /// Prepare a "POST-as-GET" request to fetch data. Low level helper.
pub fn get_request(&self, url: &str, nonce: &str) -> Result<Request, Error> { pub fn get_request(&self, url: &str, nonce: &str) -> Result<Request, Error> {
let key = PKey::private_key_from_pem(self.private_key.as_bytes())?; let key = PKey::private_key_from_pem(self.private_key.as_bytes())?;
let body = serde_json::to_string(&Jws::new_full( let body = serde_json::to_string(&Jws::new_full(
@ -93,7 +110,7 @@ impl Account {
}) })
} }
/// Prepare a JSON POST request. /// Prepare a JSON POST request. Low level helper.
pub fn post_request<T: Serialize>( pub fn post_request<T: Serialize>(
&self, &self,
url: &str, url: &str,
@ -258,18 +275,28 @@ pub struct CertificateRevocation<'a> {
} }
impl CertificateRevocation<'_> { impl CertificateRevocation<'_> {
/// Create the revocation request using the specified nonce for the given directory.
pub fn request(&self, directory: &Directory, nonce: &str) -> Result<Request, Error> { pub fn request(&self, directory: &Directory, nonce: &str) -> Result<Request, Error> {
self.account.post_request(&directory.data.revoke_cert, nonce, &self.data) self.account.post_request(&directory.data.revoke_cert, nonce, &self.data)
} }
} }
/// Status of an ACME account.
#[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Copy, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum AccountStatus { pub enum AccountStatus {
/// This is not part of the ACME API, but a temporary marker for us until the ACME provider
/// tells us the account's real status.
#[serde(rename = "<invalid>")] #[serde(rename = "<invalid>")]
New, New,
/// Means the account is valid and can be used.
Valid, Valid,
/// The account has been deactivated by its user and cannot be used anymore.
Deactivated, Deactivated,
/// The account has been revoked by the server and cannot be used anymore.
Revoked, Revoked,
} }
@ -285,30 +312,44 @@ impl AccountStatus {
} }
} }
/// ACME Account data. This is the part of the account returned from and possibly sent to the ACME
/// provider. Some fields may be uptdated by the user via a request to the account location, others
/// may not be changed.
#[derive(Clone, Deserialize, Serialize)] #[derive(Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct AccountData { pub struct AccountData {
/// The current account status.
#[serde( #[serde(
skip_serializing_if = "AccountStatus::is_new", skip_serializing_if = "AccountStatus::is_new",
default = "AccountStatus::new" default = "AccountStatus::new"
)] )]
pub status: AccountStatus, pub status: AccountStatus,
/// URLs to currently pending orders.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub orders: Option<String>, pub orders: Option<String>,
/// The acccount's contact info.
///
/// This usually contains a `"mailto:<email address>"` entry but may also contain some other
/// data if the server accepts it.
#[serde(skip_serializing_if = "Vec::is_empty", default)] #[serde(skip_serializing_if = "Vec::is_empty", default)]
pub contact: Vec<String>, pub contact: Vec<String>,
/// Indicated whether the user agreed to the ACME provider's terms of service.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub terms_of_service_agreed: Option<bool>, pub terms_of_service_agreed: Option<bool>,
/// External account information. This is currently not directly supported in any way and only
/// stored to completeness.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub external_account_binding: Option<Value>, pub external_account_binding: Option<Value>,
/// This is only used by the client when querying an account.
#[serde(default = "default_true", skip_serializing_if = "is_false")] #[serde(default = "default_true", skip_serializing_if = "is_false")]
pub only_return_existing: bool, pub only_return_existing: bool,
/// Stores unknown fields if there are any.
#[serde(flatten, default, skip_serializing_if = "HashMap::is_empty")] #[serde(flatten, default, skip_serializing_if = "HashMap::is_empty")]
pub extra: HashMap<String, Value>, pub extra: HashMap<String, Value>,
} }
@ -323,6 +364,14 @@ fn is_false(b: &bool) -> bool {
!*b !*b
} }
/// Helper to create an account.
///
/// This is used to generate a private key and set the contact info for the account. Afterwards the
/// creation request can be created via the [`request`] method, giving it a nonce and a directory.
/// This can be repeated, if necessary, like when the nonce fails.
///
/// When the server sends a succesful response, it should be passed to the [`response`] method to
/// finish the creation of an [`Account`] which can then be persisted.
#[derive(Default)] #[derive(Default)]
#[must_use = "when creating an account you must pass the response to AccountCreator::response()!"] #[must_use = "when creating an account you must pass the response to AccountCreator::response()!"]
pub struct AccountCreator { pub struct AccountCreator {