spiffe_rustls/lib.rs
1#![deny(missing_docs)]
2#![deny(unsafe_code)]
3#![warn(missing_debug_implementations)]
4#![warn(clippy::all)]
5#![warn(clippy::pedantic)]
6#![allow(clippy::module_name_repetitions)]
7#![allow(clippy::must_use_candidate)]
8
9//! # spiffe-rustls
10//!
11//! `spiffe-rustls` integrates [`rustls`] with SPIFFE/SPIRE using a live
12//! [`spiffe::X509Source`] (SPIFFE Workload API).
13//!
14//! It provides builders for [`rustls::ClientConfig`] and
15//! [`rustls::ServerConfig`] that are backed by an `X509Source`. When the SPIRE
16//! agent rotates X.509 SVIDs or trust bundles, **new TLS handshakes automatically
17//! use the updated material**, without restarting the application.
18//!
19//! The crate focuses on TLS authentication and **connection-level authorization
20//! via SPIFFE IDs**, while delegating all cryptography and TLS mechanics to
21//! `rustls`.
22//!
23//! When SPIFFE federation is configured, the crate automatically selects the correct
24//! trust domain bundle based on the peer's SPIFFE ID. Authorization is applied **after**
25//! cryptographic verification succeeds.
26//!
27//! ## Feature flags
28//!
29//! Exactly **one** `rustls` crypto provider must be enabled:
30//!
31//! * `ring` (default)
32//! * `aws-lc-rs`
33//!
34//! Enabling more than one provider results in a compile-time error.
35
36#[cfg(all(feature = "ring", feature = "aws-lc-rs"))]
37compile_error!("Enable only one crypto provider feature: `ring` or `aws-lc-rs`.");
38
39#[cfg(not(any(feature = "ring", feature = "aws-lc-rs")))]
40compile_error!("Enable one crypto provider feature: `ring` (default) or `aws-lc-rs`.");
41
42pub mod authorizer;
43
44mod crypto;
45mod error;
46mod material;
47
48mod observability;
49mod prelude;
50
51mod client;
52mod policy;
53mod resolve;
54mod server;
55mod verifier;
56
57// Public re-exports
58pub use authorizer::{any, exact, trust_domains, Authorizer};
59pub use client::ClientConfigBuilder;
60pub use error::{Error, Result};
61pub use policy::TrustDomainPolicy;
62pub use policy::TrustDomainPolicy::{AllowList, AnyInBundleSet, LocalOnly};
63pub use server::ServerConfigBuilder;
64pub use spiffe::{SpiffeId, TrustDomain};
65
66/// Constructor for the mTLS client builder.
67///
68/// Creates a client builder with default settings (accepts any SPIFFE ID, uses all bundles from the Workload API).
69///
70/// # Examples
71///
72/// ```no_run
73/// use spiffe_rustls::{authorizer, mtls_client};
74///
75/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
76/// let source = spiffe::X509Source::new().await?;
77///
78/// let client_config = mtls_client(source)
79/// .authorize(authorizer::exact([
80/// "spiffe://example.org/myservice",
81/// ])?)
82/// .build()?;
83/// # Ok(())
84/// # }
85/// ```
86pub fn mtls_client(source: spiffe::X509Source) -> ClientConfigBuilder {
87 ClientConfigBuilder::new(source)
88}
89
90/// Constructor for the mTLS server builder.
91///
92/// Creates a server builder with default settings (accepts any SPIFFE ID, uses all bundles from the Workload API).
93///
94/// # Examples
95///
96/// ```no_run
97/// use spiffe_rustls::{authorizer, mtls_server};
98///
99/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
100/// let source = spiffe::X509Source::new().await?;
101///
102/// let server_config = mtls_server(source)
103/// .authorize(authorizer::trust_domains(["example.org"])?)
104/// .build()?;
105/// # Ok(())
106/// # }
107/// ```
108pub fn mtls_server(source: spiffe::X509Source) -> ServerConfigBuilder {
109 ServerConfigBuilder::new(source)
110}