From 5f0ba968109ada1bfe828a8c7116ef2654176e20 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 5 May 2021 11:13:40 +0200 Subject: [PATCH] finish docs and #[deny(missing_docs)] at the top level Signed-off-by: Wolfgang Bumiller --- src/account.rs | 2 -- src/authorization.rs | 4 +--- src/directory.rs | 23 +++++++++++++++++++++++ src/error.rs | 6 ++++++ src/lib.rs | 21 +++++++++++++++++++-- src/order.rs | 27 ++++++++++++++++++++++++++- src/request.rs | 25 ++++++++++++++++++++++--- src/util.rs | 2 -- 8 files changed, 97 insertions(+), 13 deletions(-) diff --git a/src/account.rs b/src/account.rs index 80c844d7..bee5bc88 100644 --- a/src/account.rs +++ b/src/account.rs @@ -1,8 +1,6 @@ //! 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::convert::TryFrom; diff --git a/src/authorization.rs b/src/authorization.rs index 98633dd1..991077e0 100644 --- a/src/authorization.rs +++ b/src/authorization.rs @@ -1,7 +1,5 @@ //! Authorization and Challenge data. -#![deny(missing_docs)] - use std::collections::HashMap; use serde::{Deserialize, Serialize}; @@ -11,7 +9,7 @@ use crate::order::Identifier; use crate::request::Request; use crate::Error; -/// Authorization states. +/// Status of an [`Authorization`]. #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum Status { diff --git a/src/directory.rs b/src/directory.rs index 50294d26..474b6150 100644 --- a/src/directory.rs +++ b/src/directory.rs @@ -1,19 +1,41 @@ +//! ACME Directory information. + use serde::{Deserialize, Serialize}; +/// An ACME Directory. This contains the base URL and the directory data as received via a `GET` +/// request to the URL. pub struct Directory { + /// The main entry point URL to the ACME directory. pub url: String, + + /// The json structure received via a `GET` request to the directory URL. This contains the + /// URLs for various API entry points. pub data: DirectoryData, } /// The ACME Directory object structure. +/// +/// The data in here is typically not relevant to the user of this crate. #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct DirectoryData { + /// The entry point to create a new account. pub new_account: String, + + /// The entry point to retrieve a new nonce, should be used with a `HEAD` request. pub new_nonce: String, + + /// URL to post new orders to. pub new_order: String, + + /// URL to use for certificate revocation. pub revoke_cert: String, + + /// Account key rollover URL. pub key_change: String, + + /// Metadata object, for additional information which aren't directly part of the API + /// itself, such as the terms of service. pub meta: Meta, } @@ -21,6 +43,7 @@ pub struct DirectoryData { #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Meta { + /// The terms of service. This is typically in the form of an URL. #[serde(skip_serializing_if = "Option::is_none")] pub terms_of_service: Option, } diff --git a/src/error.rs b/src/error.rs index 89fa7ab6..56168404 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,8 +1,13 @@ +//! The `Error` type and some ACME error constants for reference. + use std::fmt; use openssl::error::ErrorStack as SslErrorStack; +/// The ACME error string for a "bad nonce" error. pub const BAD_NONCE: &str = "urn:ietf:params:acme:error:badNonce"; + +/// The ACME error string for a "user action required" error. pub const USER_ACTION_REQUIRED: &str = "urn:ietf:params:acme:error:userActionRequired"; /// Error types returned by this crate. @@ -71,6 +76,7 @@ pub enum Error { } impl Error { + /// Create an `Error` from a custom text. pub fn custom(s: T) -> Self { Error::Custom(s.to_string()) } diff --git a/src/lib.rs b/src/lib.rs index ab9258ba..3533b298 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,8 @@ //! //! The [`Account`] helper supports RSA and ECC keys and provides most of the API methods. +#![deny(missing_docs)] + mod b64u; mod json; mod jws; @@ -24,12 +26,27 @@ pub mod error; pub mod order; pub mod util; +#[doc(inline)] pub use account::Account; + +#[doc(inline)] pub use authorization::{Authorization, Challenge}; + +#[doc(inline)] pub use directory::Directory; + +#[doc(inline)] pub use error::Error; -pub use order::{NewOrder, Order}; -pub use request::{ErrorResponse, Request}; + +#[doc(inline)] +pub use order::Order; + +#[doc(inline)] +pub use request::Request; + +// we don't inline these: +pub use order::NewOrder; +pub use request::ErrorResponse; /// Header name for nonces. pub const REPLAY_NONCE: &str = "Replay-Nonce"; diff --git a/src/order.rs b/src/order.rs index a736c45a..b92c06ce 100644 --- a/src/order.rs +++ b/src/order.rs @@ -1,9 +1,12 @@ +//! ACME Orders data and identifiers. + use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::request::Request; use crate::Error; +/// Status of an [`Order`]. #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum Status { @@ -11,10 +14,22 @@ pub enum Status { /// the Acme RFC does not require the server to ignore unknown parts of the `Order` object. New, + /// Authorization failed and it is now invalid. Invalid, + + /// The authorization is pending and the user should look through its challenges. + /// + /// This is the initial state of a new authorization. Pending, + + /// The ACME provider is processing an authorization validation. Processing, + + /// The requirements for the order have been met and it may be finalized. Ready, + + /// The certificate has been issued and can be downloaded from the URL provided in the + /// [`Order`]'s `certificate` field. Valid, } @@ -26,7 +41,7 @@ impl Default for Status { impl Status { /// Serde helper - pub fn is_new(&self) -> bool { + fn is_new(&self) -> bool { *self == Status::New } @@ -53,6 +68,9 @@ pub enum Identifier { Dns(String), } +/// This contains the order data sent to and received from the ACME server. +/// +/// This is typically filled with a set of domains and then issued as a new-order request via [`Account::new_order`](crate::Account::new_order). #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct OrderData { @@ -96,16 +114,20 @@ pub struct OrderData { } impl OrderData { + /// Initialize an empty order object. pub fn new() -> Self { Default::default() } + /// Builder-style method to add a domain identifier to the data. pub fn domain(mut self, domain: String) -> Self { self.identifiers.push(Identifier::Dns(domain)); self } } +/// Represents an order for a new certificate. This combines the order's own location (URL) with +/// the [`OrderData`] received from the ACME server. #[derive(Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct Order { @@ -133,6 +155,9 @@ impl Order { /// This is created via [`Account::new_order`](crate::Account::new_order()). pub struct NewOrder { //order: OrderData, + + /// The request to execute to place the order. When creating a [`NewOrder`] via + /// [`Account::new_order`](crate::Account::new_order) this is guaranteed to be `Some`. pub request: Option, } diff --git a/src/request.rs b/src/request.rs index 4cd929ab..78a90913 100644 --- a/src/request.rs +++ b/src/request.rs @@ -1,23 +1,42 @@ use serde::Deserialize; -pub const JSON_CONTENT_TYPE: &str = "application/jose+json"; - -pub const CREATED: u16 = 201; +pub(crate) const JSON_CONTENT_TYPE: &str = "application/jose+json"; +pub(crate) const CREATED: u16 = 201; /// A request which should be performed on the ACME provider. pub struct Request { + /// The complete URL to send the request to. pub url: String, + + /// The HTTP method name to use. pub method: &'static str, + + /// The `Content-Type` header to pass along. pub content_type: &'static str, + + /// The body to pass along with request, or an empty string. pub body: String, + /// The expected status code a compliant ACME provider will return on success. pub expected: u16, } +/// An ACME error response contains a specially formatted type string, and can optionally +/// contain textual details and a set of sub problems. #[derive(Clone, Debug, Deserialize)] pub struct ErrorResponse { + /// The ACME error type string. + /// + /// Most of the time we're only interested in the "bad nonce" or "user action required" + /// errors. When an [`Error`](crate::Error) is built from this error response, it will map + /// to the corresponding enum values (eg. [`Error::BadNonce`](crate::Error::BadNonce)). #[serde(rename = "type")] pub ty: String, + + /// A textual detail string optionally provided by the ACME provider to inform the user more + /// verbosely about why the error occurred. pub detail: Option, + + /// Additional json data containing information as to why the error occurred. pub subproblems: Option, } diff --git a/src/util.rs b/src/util.rs index 6b48e717..7242b643 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,5 @@ //! Certificate utility methods for convenience (such as CSR generation). -#![deny(missing_docs)] - use std::collections::HashMap; use openssl::hash::MessageDigest;