Why Zero Trust Architecture
Never trust, always verify—even inside the network
The Problem
Traditional network security assumes a perimeter. Inside the firewall is trusted; outside is untrusted. Build a strong wall, and you're safe.
This model is broken.
The perimeter no longer exists.
Remote work means employees connect from anywhere. Cloud services mean data lives outside your network. Microservices mean components communicate across trust boundaries constantly.
A single compromised credential, a single vulnerable service, and attackers move laterally through your "trusted" network with impunity. The perimeter was always an illusion—now it's an obviously false one.
We needed a security model that:
- Assumes the network is already compromised
- Verifies every request, regardless of source
- Limits blast radius when breaches occur
- Works across cloud, on-premise, and hybrid environments
Current Options
| Option | Pros | Cons |
|---|---|---|
| Perimeter SecurityTraditional firewall-based approach. Trust the internal network. |
|
|
| Zero TrustVerify every request. No implicit trust based on network location. |
|
|
| Hybrid ApproachPerimeter for legacy, Zero Trust for new systems. |
|
|
Future Outlook
Zero Trust is becoming the only trust model that makes sense.
Every major framework now assumes Zero Trust.
NIST, CISA, and industry standards all recommend Zero Trust architecture. Cloud providers build their services around it. The question isn't whether to adopt Zero Trust but how fast.
The convergence of AI and security accelerates this. AI-powered attacks are more sophisticated, faster, and more targeted. AI-powered defenses require the granular visibility that Zero Trust provides.
The future is identity-centric, context-aware, continuous verification. Every request carries identity, context, and intent. Every response is scoped to minimum necessary access.
Our Decision
✓Why we chose this
- Defense in depthMultiple verification layers mean single failures don't cause breaches
- Limited blast radiusCompromised credentials can only access what they're explicitly authorized for
- Cloud-native compatibilityWorks naturally with distributed, multi-cloud architectures
- Compliance alignmentMeets modern regulatory frameworks and audit requirements
×Trade-offs we accept
- Implementation complexityRequires identity providers, policy engines, and continuous verification
- Performance overheadEvery request requires authentication and authorization checks
- Cultural changeTeams must shift from 'trusted network' thinking
Motivation
We build systems that handle business-critical data. A breach isn't just embarrassing—it's potentially catastrophic for the businesses that trust us.
Zero Trust isn't paranoia; it's realism. We assume our network could be compromised. We assume credentials could be stolen. We assume any component could be malicious.
Every service-to-service call carries authentication. Every request is authorized against policy. Every action is logged for audit. This isn't overhead—it's the cost of doing business responsibly.
Recommendation
Implement Zero Trust for Converge's gRPC + NATS architecture:
1. mTLS everywhere
- gRPC services:
tonicwithrustlsfor client/server certificates - NATS connections: TLS with client certificate authentication
- No plaintext service communication, ever
2. Service identity via SPIFFE/SPIRE
- Each service gets a cryptographic identity (SVID)
- Identity verified on every connection
- Short-lived certificates, automatic rotation
3. Request-level authorization
- gRPC interceptors validate JWT claims + service identity
- NATS: subject-based permissions tied to service identity
- Policy engine (Cedar or OPA) for complex rules
4. Audit everything
- Every gRPC call logged with identity context
- NATS JetStream for durable audit trail
- Correlation IDs across service boundaries
Don't build custom auth. Use: Firebase Auth (users), SPIFFE (services), Cloud IAM (infrastructure).
Examples
use tonic::{Request, Status, service::Interceptor};
/// Zero Trust interceptor - verify identity on every gRPC call
#[derive(Clone)]
pub struct AuthInterceptor {
jwt_validator: JwtValidator,
policy_engine: PolicyEngine,
}
impl Interceptor for AuthInterceptor {
fn call(&mut self, mut request: Request<()>) -> Result<Request<()>, Status> {
// 1. Extract service identity from mTLS (already verified by TLS layer)
let peer_cert = request.peer_certs()
.ok_or_else(|| Status::unauthenticated("no client certificate"))?;
let service_id = extract_spiffe_id(peer_cert)?;
// 2. Extract user identity from JWT (if present)
let user_id = request.metadata()
.get("authorization")
.and_then(|h| h.to_str().ok())
.and_then(|token| self.jwt_validator.validate(token).ok());
// 3. Check policy - service + user + method = allowed?
let method = request.uri().path();
let decision = self.policy_engine.check(PolicyRequest {
service_id: &service_id,
user_id: user_id.as_deref(),
method,
})?;
if !decision.allowed {
return Err(Status::permission_denied(decision.reason));
}
// 4. Attach verified identity for downstream use
request.extensions_mut().insert(VerifiedIdentity {
service_id,
user_id,
permissions: decision.permissions,
});
Ok(request)
}
}gRPC interceptor verifies both service identity (mTLS/SPIFFE) and user identity (JWT). Every call is authenticated and authorized—no implicit trust.
use async_nats::{Client, ConnectOptions};
/// Create NATS client with mTLS - Zero Trust for messaging
pub async fn connect_nats(config: &NatsConfig) -> Result<Client, NatsError> {
let tls_config = rustls::ClientConfig::builder()
.with_root_certificates(load_ca_certs(&config.ca_cert)?)
.with_client_auth_cert(
load_cert_chain(&config.client_cert)?,
load_private_key(&config.client_key)?,
)?;
let client = ConnectOptions::new()
.tls_config(tls_config)
.user_and_password(config.nkey_user.clone(), config.nkey_seed.clone())
.connect(&config.servers)
.await?;
// NATS server enforces subject permissions based on client cert identity
// e.g., service "pricing" can only publish to "pricing.>" subjects
Ok(client)
}NATS connections use mTLS for identity. Server enforces subject-level permissions per service—no service can publish/subscribe outside its authorized subjects.