| Crates.io | spiffe |
| lib.rs | spiffe |
| version | 0.11.3 |
| created_at | 2021-06-15 16:47:24.99241+00 |
| updated_at | 2026-01-22 04:14:50.493095+00 |
| description | Core SPIFFE identity types and Workload API sources |
| homepage | |
| repository | https://github.com/maxlambrecht/rust-spiffe |
| max_upload_size | |
| id | 410519 |
| size | 558,737 |
Core SPIFFE identity types and Workload API sources.
This crate provides SPIFFE identity primitives (SpiffeId, TrustDomain) and clients for the
SPIFFE Workload API (X509Source, JwtSource, WorkloadApiClient). It handles X.509 and JWT
SVIDs, trust bundles, and streaming updates. All cryptography and TLS integration are intentionally delegated to other crates.
Add spiffe to your Cargo.toml. All features are opt-in:
[dependencies]
# Minimal: only SPIFFE primitives
spiffe = "0.11"
# OR X.509 workloads (recommended)
# spiffe = { version = "0.11", features = ["x509-source"] }
# OR JWT workloads (recommended)
# spiffe = { version = "0.11", features = ["jwt-source"] }
# OR Direct Workload API usage
# spiffe = { version = "0.11", features = ["workload-api"] }
Using an explicit socket path:
use spiffe::WorkloadApiClient;
let client = WorkloadApiClient::connect_to(
"unix:/tmp/spire-agent/public/api.sock",
).await?;
Or via the SPIFFE_ENDPOINT_SOCKET environment variable:
use spiffe::WorkloadApiClient;
let client = WorkloadApiClient::connect_env().await?;
The Workload API client exposes low-level access to X.509 materials.
use spiffe::{TrustDomain, X509Context};
let context: X509Context = client.fetch_x509_context().await?;
let trust_domain = TrustDomain::new("example.org")?;
let bundle = context
.bundle_set()
.get(&trust_domain)
.ok_or("missing bundle")?;
use futures_util::StreamExt;
let mut stream = client.stream_x509_contexts().await?;
while let Some(update) = stream.next().await {
let context = update?;
// react to updated SVIDs and bundles
}
X509Source (recommended)X509Source is a higher-level abstraction built on top of the Workload API.
It maintains a locally cached, automatically refreshed view of X.509 SVIDs and bundles, handling reconnections and rotations transparently.
use spiffe::{TrustDomain, X509Source};
let source = X509Source::new().await?;
// Snapshot of current materials
let context = source.x509_context()?;
// Selected SVID (default or picker)
let svid = source.svid()?;
// Bundle for a trust domain
let trust_domain = TrustDomain::new("example.org")?;
let bundle = source
.bundle_for_trust_domain(&trust_domain)?
.ok_or("missing bundle")?;
For most X.509-based workloads, X509Source provides a higher-level API.
JwtSource (recommended)JwtSource is a higher-level abstraction built on top of the Workload API for JWT workloads.
It maintains a locally cached, automatically refreshed view of JWT bundles, handling reconnections and rotations transparently. JWT SVIDs are fetched on-demand with specific audiences.
use spiffe::{TrustDomain, JwtSource};
let source = JwtSource::new().await?;
// Fetch JWT SVID for specific audiences
let jwt_svid = source.get_jwt_svid(&["service-a", "service-b"]).await?;
// Fetch JWT SVID for a specific SPIFFE ID
let spiffe_id = "spiffe://example.org/my-service".parse()?;
let jwt_svid = source.get_jwt_svid_with_id(&["audience"], Some(&spiffe_id)).await?;
// Bundle for a trust domain
let trust_domain = TrustDomain::new("example.org")?;
let bundle = source
.bundle_for_trust_domain(&trust_domain)?
.ok_or("missing bundle")?;
For most JWT-based workloads, JwtSource provides a higher-level API.
When multiple SVIDs are returned by the Workload API, SPIRE may attach an
operator-defined hint (for example, internal or external) to guide selection.
Hints are not part of the cryptographic identity. They are metadata returned by the Workload API and are exposed by this crate for convenience.
X509SvidJwtSvidHigher-level abstractions like X509Source preserve hints and allow custom
selection logic via SvidPicker.
JwtSource (recommended)For most JWT workloads, use JwtSource which provides automatic bundle caching and on-demand SVID fetching:
use spiffe::JwtSource;
let source = JwtSource::new().await?;
// Fetch JWT SVID
let jwt_svid = source.get_jwt_svid(&["audience1", "audience2"]).await?;
See the JwtSource section above for more details.
For direct access without caching, use the Workload API client:
use spiffe::{SpiffeId, WorkloadApiClient};
let client = WorkloadApiClient::connect_env().await?;
let spiffe_id = SpiffeId::try_from("spiffe://example.org/my-service")?;
let jwt = client
.fetch_jwt_svid(&["audience1", "audience2"], Some(&spiffe_id))
.await?;
use futures_util::StreamExt;
use spiffe::TrustDomain;
use spiffe::WorkloadApiClient;
let client = WorkloadApiClient::connect_env().await?;
let bundles = client.fetch_jwt_bundles().await?;
let trust_domain = TrustDomain::try_from("example.org")?;
let bundle = bundles.get(&trust_domain);
let mut stream = client.stream_jwt_bundles().await?;
while let Some(update) = stream.next().await {
let bundles = update?;
// react to updated JWT authorities
}
This crate supports three distinct JWT-SVID usage patterns, depending on where verification happens.
JWT-SVIDs fetched directly from the SPIFFE Workload API are trusted by construction. The SPIRE agent already authenticated the workload and issued the token.
use spiffe::JwtSvid;
let svid = JwtSvid::from_workload_api_token(token_str)?;
No additional features are required.
The Workload API exposes a validation RPC.
WorkloadApiClient::validate_jwt_token delegates verification to the SPIRE agent
and returns a parsed JwtSvid.
use spiffe::WorkloadApiClient;
let client = WorkloadApiClient::connect_env().await?;
let svid = client
.validate_jwt_token("my-audience", jwt_token)
.await?;
Characteristics:
If you need to validate untrusted JWTs locally (for example, tokens received over the network), enable offline JWT verification with an explicit cryptographic backend.
[dependencies]
spiffe = { version = "0.11", features = ["jwt-verify-rust-crypto"] }
[dependencies]
spiffe = { version = "0.11", features = ["jwt-verify-aws-lc-rs"] }
This enables local signature verification using JWT authorities from bundles:
use spiffe::JwtSvid;
let svid = JwtSvid::parse_and_validate(
token_str,
&bundle_source,
&["expected-audience"],
)?;
Use this mode when:
All features are additive and opt-in. The crate has no default features (default = []).
x509Enables X.509 SVID and bundle types plus parsing. Gates heavy ASN.1/X.509 dependencies (asn1, x509-parser, pkcs8).
Note: Most users should enable x509-source instead, which includes this feature automatically.
transportLightweight endpoint parsing and normalization. No runtime dependencies (pure parsing logic).
transport-grpcgRPC connector for Unix/TCP endpoints. Requires transport and adds tokio/tonic/tower dependencies.
workload-apiEnables the async SPIFFE Workload API client. Requires transport-grpc and x509.
Provides:
WorkloadApiClient and streaming APIsvalidate_jwt_token)x509-sourceHigh-level X.509 watcher and caching abstraction. Requires workload-api (and transitively x509).
Provides:
X509Source for automatic SVID/bundle watching and cachingjwt-sourceHigh-level JWT watcher and caching abstraction. Requires workload-api and jwt.
Provides:
JwtSource for automatic bundle watching and cachingjwtEnables JWT SVID and bundle types plus parsing. Gates JWT-related dependencies (serde, serde_json, time,
base64ct).
Note: JWT verification requires an additional backend feature (see below).
jwt-verify-rust-cryptoEnables offline JWT-SVID verification using a pure Rust cryptography backend.
When enabled, [JwtSvid::parse_and_validate] performs JWT-SVID validation:
exp claim: tokens must not be expiredaud claim: must intersect the expected_audience parameter
(empty audience arrays are rejected)sub claim: must be present and parse as a valid SPIFFE IDkid header: must be present and match a key in the bundleNote: nbf, iat, and iss claims are not validated. See the
[JwtSvid::parse_and_validate] documentation for complete details.
use spiffe::{bundle::BundleSource, JwtBundle, JwtSvid};
fn validate_token<B: BundleSource<Item = JwtBundle>>(
token: &str,
bundles: &B,
) -> Result<JwtSvid, spiffe::JwtSvidError> {
JwtSvid::parse_and_validate(token, bundles, &["my-service"])
}
jwt-verify-aws-lc-rsEnables offline JWT-SVID verification using AWS-LC via aws-lc-rs.
jwt-verify-rust-cryptoValidation semantics are identical to jwt-verify-rust-crypto; only the cryptographic
backend differs.
The crate supports optional observability through two mutually compatible features:
logging and tracing. Both features are optional and can be enabled independently
or together.
When multiple observability features are enabled, the following precedence applies:
tracing (highest priority) — If enabled, all events are emitted via tracinglogging — If tracing is not enabled, events are emitted via the log crateloggingEnables observability using the log crate.
This is a lightweight option suitable for applications that use the standard log
facade. Events are emitted via log::debug!, log::info!, log::warn!, and log::error!.
[dependencies]
spiffe = { version = "0.11", features = ["logging"] }
Note: The logging feature is not included in the default workload-api feature.
You must explicitly enable it if you want log output.
tracingEnables structured observability using the tracing crate.
This is recommended for production environments that use structured logs, spans,
or distributed tracing systems. When both tracing and logging features are enabled,
tracing takes precedence and all events are emitted via tracing macros.
[dependencies]
spiffe = { version = "0.11", features = ["tracing"] }
Note: The tracing and logging features are not mutually exclusive. When both
features are enabled, events are emitted via tracing.
In addition to the higher-level bundles (workload-api-x509, workload-api-jwt,
workload-api, workload-api-full), the crate exposes a lower-level
workload-api-core feature:
[dependencies]
spiffe = { version = "0.11", features = ["workload-api-core"] }
This feature includes:
transport-grpc): endpoint parsing and gRPC connectortokio, tonic, tokio-stream, tokio-utilExcluded (not included in workload-api-core):
x509 feature)jwt feature)Use workload-api-core if you want to build a custom client or integrate with
alternative SVID/bundle representations while reusing the transport layer.
jwt-verify-rust-crypto, jwt-verify-aws-lc-rs) is self-contained and automatically includes
the jwt featureWorkloadApiClient::validate_jwt_tokenPerformance characteristics:
X509Source and JwtSource (no locks on read path)The X509Source and JwtSource maintain cached views of SVIDs and bundles, updating atomically when the Workload API delivers new
material. This eliminates the need for polling and ensures new handshakes always use the latest credentials.
The crate is organized into several layers:
SpiffeId, TrustDomain) — Always available, no dependenciestransport, transport-grpc) — Endpoint parsing and gRPC connectivityworkload-api-*) — Low-level client for SPIFFE Workload APIx509-source, jwt-source) — Automatic caching and rotation handlingThis layered design allows you to use only what you need, minimizing dependencies and compile times.
SPIFFE_ENDPOINT_SOCKET environment variable or socket pathjwt-verify-* features)X509Source or JwtSource for automatic rotation instead of manual pollinglogging or tracing) in production for monitoringFor security vulnerabilities, see SECURITY.md.
This project runs cargo audit in CI. Some advisories may appear only when enabling optional features
(e.g., offline JWT verification). At the time of writing, cargo audit may report RUSTSEC-2023-0071
(the rsa crate “Marvin Attack” advisory) via jsonwebtoken, and there is currently no fixed upgrade
available upstream.
If you require a clean audit, avoid enabling offline JWT verification unless needed, or temporarily ignore the advisory until upstream releases a fix.
Licensed under the Apache License, Version 2.0. See LICENSE for details.