tokio_rustls_acme/
lib.rs

1//! An easy-to-use, async compatible [ACME] client library using [rustls] with [ring].
2//! The validation mechanism used is tls-alpn-01, which allows serving acme challenge responses and
3//! regular TLS traffic on the same port.
4//!
5//! Is designed to use the tokio runtime, if you need support for other runtimes take a look
6//! at the original implementation [rustls-acme](https://github.com/FlorianUekermann/rustls-acme).
7//!
8//! No persistent tasks are spawned under the hood and the certificate acquisition/renewal process
9//! is folded into the streams and futures being polled by the library user.
10//!
11//! The goal is to provide a [Let's Encrypt](https://letsencrypt.org/) compatible TLS serving and
12//! certificate management using a simple and flexible stream based API.
13//!
14//! This crate uses [ring] as [rustls]'s backend, instead of [aws-lc-rs]. This generally makes it
15//! much easier to compile. If you'd like to use [aws-lc-rs] as [rustls]'s backend, we're open to
16//! contributions with the necessary `Cargo.toml` changes and feature-flags to enable you to do so.
17//!
18//! To use tokio-rustls-acme add the following lines to your `Cargo.toml`:
19//!
20//! ```toml
21//! [dependencies]
22//! tokio-rustls-acme = "*"
23//! ```
24//!
25//! ## High-level API
26//!
27//! The high-level API consists of a single stream [Incoming] of incoming TLS connection.
28//! Polling the next future of the stream takes care of acquisition and renewal of certificates, as
29//! well as accepting TLS connections, which are handed over to the caller on success.
30//!
31//! ```rust,no_run
32//! use tokio::io::AsyncWriteExt;
33//! use futures::StreamExt;
34//! use tokio_rustls_acme::{AcmeConfig, caches::DirCache};
35//! use tokio_stream::wrappers::TcpListenerStream;
36//!
37//! #[tokio::main]
38//! async fn main() {
39//!     simple_logger::init_with_level(log::Level::Info).unwrap();
40//!
41//!     let tcp_listener = tokio::net::TcpListener::bind("[::]:443").await.unwrap();
42//!     let tcp_incoming = TcpListenerStream::new(tcp_listener);
43//!
44//!     let mut tls_incoming = AcmeConfig::new(["example.com"])
45//!         .contact_push("mailto:admin@example.com")
46//!         .cache(DirCache::new("./rustls_acme_cache"))
47//!         .incoming(tcp_incoming, Vec::new());
48//!
49//!     while let Some(tls) = tls_incoming.next().await {
50//!         let mut tls = tls.unwrap();
51//!         tokio::spawn(async move {
52//!             tls.write_all(HELLO).await.unwrap();
53//!             tls.shutdown().await.unwrap();
54//!         });
55//!     }
56//! }
57//!
58//! const HELLO: &'static [u8] = br#"HTTP/1.1 200 OK
59//! Content-Length: 11
60//! Content-Type: text/plain; charset=utf-8
61//!
62//! Hello Tls!"#;
63//! ```
64//!
65//! `examples/high_level.rs` implements a "Hello Tls!" server similar to the one above, which accepts
66//! domain, port and cache directory parameters.
67//!
68//! Note that all examples use the let's encrypt staging directory by default.
69//! The production directory imposes strict rate limits, which are easily exhausted accidentally
70//! during testing and development.
71//! For testing with the staging directory you may open `https://<your domain>:<port>` in a browser
72//! that allows TLS connections to servers signed by an untrusted CA (in Firefox click "Advanced..."
73//! -> "Accept the Risk and Continue").
74//!
75//! ## Low-level Rustls API
76//!
77//! For users who may want to interact with [rustls] or [tokio_rustls]
78//! directly, the library exposes the underlying certificate management [AcmeState] as well as a
79//! matching resolver [ResolvesServerCertAcme] which implements the [rustls::server::ResolvesServerCert] trait.
80//! See the server_low_level example on how to use the low-level API directly with [tokio_rustls].
81//!
82//! ## Account and certificate caching
83//!
84//! A production server using the let's encrypt production directory must implement both account and
85//! certificate caching to avoid exhausting the let's encrypt API rate limits.
86//! A file based cache using a cache directory is provided by [caches::DirCache].
87//! Caches backed by other persistence layers may be implemented using the [Cache] trait,
88//! or the underlying [CertCache], [AccountCache] traits (contributions welcome).
89//! [caches::CompositeCache] provides a wrapper to combine two implementors of [CertCache] and
90//! [AccountCache] into a single [Cache].
91//!
92//! Note, that the error type parameters of the cache carries over to some other types in this
93//! crate via the [AcmeConfig] they are added to.
94//! If you want to avoid different specializations based on cache type use the
95//! [AcmeConfig::cache_with_boxed_err] method to construct the an [AcmeConfig] object.
96//!
97//!
98//! ## The acme module
99//!
100//! The underlying implementation of an async acme client may be useful to others and is exposed as
101//! a module. It is incomplete (contributions welcome) and not covered by any stability
102//! promises.
103//!
104//! ## Special thanks
105//!
106//! This crate was inspired by the [autocert](https://golang.org/x/crypto/acme/autocert/)
107//! package for [Go](https://golang.org).
108//!
109//! The original implementation of this crate can be found at [FlorianUekermann/rustls-acme](https://github.com/FlorianUekermann/rustls-acme/commits/main), this is just a version focused on supporting only tokio.
110//!
111//! This crate also builds on the excellent work of the authors of
112//! [rustls],
113//! [tokio-rustls](https://github.com/tokio-rs/tls/tree/master/tokio-rustls) and many others.
114//!
115//! [ACME]: https://en.wikipedia.org/wiki/Automatic_Certificate_Management_Environment
116//! [ring]: https://github.com/briansmith/ring
117//! [rustls]: https://github.com/ctz/rustls
118//! [aws-lc-rs]: https://github.com/aws/aws-lc-rs
119
120#![cfg_attr(docsrs, feature(doc_auto_cfg))]
121
122mod acceptor;
123pub mod acme;
124#[cfg(feature = "axum")]
125pub mod axum;
126mod cache;
127pub mod caches;
128mod config;
129mod https_helper;
130mod incoming;
131mod jose;
132mod resolver;
133mod state;
134
135pub use tokio_rustls;
136
137pub use acceptor::*;
138pub use cache::*;
139pub use config::*;
140pub use incoming::*;
141pub use resolver::*;
142pub use state::*;