Skip to main content

spiffe_rustls/
lib.rs

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