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