acme2_eab/
lib.rs

1//! # acme2-eab
2//!
3//! NOTE: this is a fork of [acme2](https://crates.io/crates/acme2) which
4//! adds support for [External Account Binding](https://tools.ietf.org/html/rfc8555#section-7.3.4).
5//!
6//! A [Tokio](https://crates.io/crates/tokio) and
7//! [OpenSSL](https://crates.io/crates/openssl) based
8//! [ACMEv2](https://tools.ietf.org/html/rfc8555) client.
9//!
10//! Features:
11//!
12//! - ACME v2 support, tested against Let's Encrypt and Pebble
13//! - Fully async, using `reqwest` / Tokio
14//! - Support for DNS01 and HTTP01 validation
15//! - Fully instrumented with `tracing`
16//!
17//! ## Example
18//!
19//! This example demonstrates how to provision a certificate for the domain
20//! `example.com` using `http-01` validation.
21//!
22//! ```no_run
23//! use acme2_eab::gen_rsa_private_key;
24//! use acme2_eab::AccountBuilder;
25//! use acme2_eab::AuthorizationStatus;
26//! use acme2_eab::ChallengeStatus;
27//! use acme2_eab::DirectoryBuilder;
28//! use acme2_eab::OrderBuilder;
29//! use acme2_eab::OrderStatus;
30//! use acme2_eab::Csr;
31//! use acme2_eab::Error;
32//! use std::time::Duration;
33//!
34//! const LETS_ENCRYPT_URL: &'static str =
35//!   "https://acme-v02.api.letsencrypt.org/directory";
36//!
37//! #[tokio::main]
38//! async fn main() -> Result<(), Error> {
39//!   // Create a new ACMEv2 directory for Let's Encrypt.
40//!   let dir = DirectoryBuilder::new(LETS_ENCRYPT_URL.to_string())
41//!     .build()
42//!     .await?;
43//!
44//!   // Create an ACME account to use for the order. For production
45//!   // purposes, you should keep the account (and private key), so
46//!   // you can renew your certificate easily.
47//!   let mut builder = AccountBuilder::new(dir.clone());
48//!   builder.contact(vec!["mailto:hello@lcas.dev".to_string()]);
49//!   builder.terms_of_service_agreed(true);
50//!   let account = builder.build().await?;
51//!
52//!   // Create a new order for a specific domain name.
53//!   let mut builder = OrderBuilder::new(account);
54//!   builder.add_dns_identifier("example.com".to_string());
55//!   let order = builder.build().await?;
56//!
57//!   // Get the list of needed authorizations for this order.
58//!   let authorizations = order.authorizations().await?;
59//!   for auth in authorizations {
60//!     // Get an http-01 challenge for this authorization (or panic
61//!     // if it doesn't exist).
62//!     let challenge = auth.get_challenge("http-01").unwrap();
63//!
64//!     // At this point in time, you must configure your webserver to serve
65//!     // a file at `https://example.com/.well-known/${challenge.token}`
66//!     // with the content of `challenge.key_authorization()??`.
67//!
68//!     // Start the validation of the challenge.
69//!     let challenge = challenge.validate().await?;
70//!
71//!     // Poll the challenge every 5 seconds until it is in either the
72//!     // `valid` or `invalid` state.
73//!     let challenge = challenge.wait_done(Duration::from_secs(5), 3).await?;
74//!
75//!     assert_eq!(challenge.status, ChallengeStatus::Valid);
76//!
77//!     // You can now remove the challenge file hosted on your webserver.
78//!
79//!     // Poll the authorization every 5 seconds until it is in either the
80//!     // `valid` or `invalid` state.
81//!     let authorization = auth.wait_done(Duration::from_secs(5), 3).await?;
82//!     assert_eq!(authorization.status, AuthorizationStatus::Valid)
83//!   }
84//!
85//!   // Poll the order every 5 seconds until it is in either the
86//!   // `ready` or `invalid` state. Ready means that it is now ready
87//!   // for finalization (certificate creation).
88//!   let order = order.wait_ready(Duration::from_secs(5), 3).await?;
89//!
90//!   assert_eq!(order.status, OrderStatus::Ready);
91//!
92//!   // Generate an RSA private key for the certificate.
93//!   let pkey = gen_rsa_private_key(4096)?;
94//!
95//!   // Create a certificate signing request for the order, and request
96//!   // the certificate.
97//!   let order = order.finalize(Csr::Automatic(pkey)).await?;
98//!
99//!   // Poll the order every 5 seconds until it is in either the
100//!   // `valid` or `invalid` state. Valid means that the certificate
101//!   // has been provisioned, and is now ready for download.
102//!   let order = order.wait_done(Duration::from_secs(5), 3).await?;
103//!
104//!   assert_eq!(order.status, OrderStatus::Valid);
105//!
106//!   // Download the certificate, and panic if it doesn't exist.
107//!   let cert = order.certificate().await?.unwrap();
108//!   assert!(cert.len() > 1);
109//!
110//!   Ok(())
111//! }
112//! ```
113//!
114mod account;
115mod authorization;
116mod directory;
117mod error;
118mod helpers;
119mod jws;
120mod order;
121
122pub use account::*;
123pub use authorization::*;
124pub use directory::*;
125pub use error::Error;
126pub use error::ServerError;
127pub use error::TransportError;
128pub use helpers::gen_ec_p256_private_key;
129pub use helpers::gen_rsa_private_key;
130pub use helpers::Identifier;
131pub use openssl;
132pub use order::*;