dwara_core/mesh/
mod.rs

1//! Service mesh mode (DW-107): sidecar traffic interception plus
2//! SPIFFE/SPIRE mTLS identity.
3//!
4//! This module is SCAFFOLDED (Enterprise-only). The
5//! service mesh mode runs dwara as a SIDECAR in each pod: an init
6//! container configures iptables (or TPROXY) redirects so all inbound
7//! traffic to the local application and all outbound traffic from the
8//! local application to remote services flows through the sidecar. The
9//! sidecar then terminates mTLS on inbound connections (verifying the
10//! peer's SPIFFE SVID, applying policies, then forwarding to the local
11//! app over loopback) and wraps outbound connections in mTLS (applying
12//! policies, then dialing the remote service's sidecar with the local
13//! workload's SVID).
14//!
15//! Identity is provided by SPIFFE/SPIRE: each workload fetches X.509
16//! SVIDs (SPIFFE Verifiable Identity Documents) from the SPIRE Workload
17//! API over a Unix domain socket. The SVID certificate's URI SAN carries
18//! the SPIFFE ID (`spiffe://<trust-domain>/<path>`), which is the
19//! authentication identity used for policy decisions. The trust bundle
20//! (the SPIRE signing CAs) is used to verify peer SVIDs.
21//!
22//! # What is implemented today
23//!
24//! The scaffold compiles and the config schema is always present so
25//! configs round-trip without the feature. What is implemented:
26//!
27//! - [`spiffe::SpiffeClient`]: the Workload API client is implemented
28//!   behind a transport abstraction ([`spiffe::WorkloadApiTransport`]).
29//!   The production gRPC transport (`spiffe::grpc::GrpcWorkloadApi`)
30//!   uses tonic over a Unix domain socket (ent-gated); a test fake
31//!   ([`spiffe::FakeWorkloadApi`]) is provided for deterministic tests.
32//!   The client fetches X.509 SVIDs and the trust bundle, and exposes
33//!   the refresh-result metric seam. The SVID material (cert chain,
34//!   private key, expiry) and the trust bundle (CA certs) are the
35//!   integration point for `security::tls`.
36//!
37//! What is STUBBED (documented no-ops pending production hardening):
38//!
39//! - [`sidecar::SidecarController`]: the inbound/outbound listener
40//!   configuration and the iptables/TPROXY redirect bootstrap are
41//!   scaffolded. The controller records the configured listeners and
42//!   documents the redirect setup, but does NOT install iptables rules
43//!   or open sockets (that wiring lands when the sidecar bootstrap is
44//!   production-ready).
45//! - The full gRPC client wiring in `spiffe::grpc::GrpcWorkloadApi`:
46//!   the transport abstraction and the trait-based seam are landed; the
47//!   full gRPC call (proto-generated client, codec, path) is the
48//!   remaining wiring. The `connect()` method establishes the tonic
49//!   channel over the Unix socket; the fetch methods return a clear
50//!   "not yet connected" error until the proto client is wired.
51//!
52//! # Gating
53//!
54//! The scaffold compiles into every build (there is no `mesh` cargo
55//! feature). The `mesh` config block is accepted but inert: validation
56//! warns, and no sidecar listeners or SPIFFE client are wired until the
57//! sidecar bootstrap is production-ready. Ent-only: validation warns
58//! when mesh is configured without the `ent` feature (mirrors the
59//! FIPS/credential-pool ent-gate pattern).
60//!
61//! # Dependency direction
62//!
63//! `mesh` depends on `config` (the config schema) and `observability`
64//! (the mesh/SPIFFE metrics). It does NOT import `security` directly:
65//! the TLS integration point is a documented seam (the mTLS TLS config
66//! in `security::tls` would consume the SVID cert/key and trust bundle
67//! produced here), kept as a seam so the dependency direction stays
68//! downward (mesh is a peer of security, both above config).
69
70pub mod sidecar;
71pub mod spiffe;
72
73pub use sidecar::{SidecarConfig, SidecarController, SidecarMode, SidecarRedirectMode};
74pub use spiffe::{
75    FakeWorkloadApi, SpiffeClient, SpiffeConfig, SpiffeError, SpiffeIdentity, SpiffeSvid,
76    SpiffeTrustBundle, SvidRefreshResult, WorkloadApiTransport,
77};