Zero-Trust security patterns — mTLS between microservices (Istio/SPIFFE), SPIRE workload identity, OPA/Envoy authorization, NetworkPolicy default-deny-all, short-lived credentials, service mesh security, and Kubernetes RBAC hardening.
From clarcnpx claudepluginhub marvinrichter/clarc --plugin clarcThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
Zero-Trust Architecture operates on four pillars:
SPIFFE (Secure Production Identity Framework for Everyone) is the standard for cryptographic service identities.
spiffe://trust-domain/path/to/workload
# Example:
spiffe://prod.example.com/ns/payments/sa/checkout-service
# spire-server.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: spire-server
namespace: spire
spec:
replicas: 1
selector:
matchLabels:
app: spire-server
template:
spec:
containers:
- name: spire-server
image: ghcr.io/spiffe/spire-server:1.9.0
args:
- -config
- /run/spire/config/server.conf
volumeMounts:
- name: spire-config
mountPath: /run/spire/config
- name: spire-data
mountPath: /run/spire/data
# server.conf
server {
bind_address = "0.0.0.0"
bind_port = "8081"
trust_domain = "prod.example.com"
data_dir = "/run/spire/data"
log_level = "INFO"
# JWT SVIDs for service-to-service auth
jwt_issuer = "https://spire-server.spire.svc.cluster.local"
}
plugins {
DataStore "sql" {
plugin_data {
database_type = "sqlite3"
connection_string = "/run/spire/data/datastore.sqlite3"
}
}
NodeAttestor "k8s_psat" {
plugin_data {
clusters = {
"my-cluster" = {
service_account_allow_list = ["spire:spire-agent"]
}
}
}
}
KeyManager "memory" {
plugin_data {}
}
}
# Register a workload (checkout-service in payments namespace)
kubectl exec -n spire spire-server-0 -- \
/opt/spire/bin/spire-server entry create \
-spiffeID spiffe://prod.example.com/ns/payments/sa/checkout-service \
-parentID spiffe://prod.example.com/k8s-node/node1 \
-selector k8s:ns:payments \
-selector k8s:sa:checkout-service
import (
"github.com/spiffe/go-spiffe/v2/workloadapi"
"github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig"
)
func newTLSConfig(ctx context.Context) (*tls.Config, error) {
source, err := workloadapi.NewX509Source(ctx)
if err != nil {
return nil, fmt.Errorf("create x509 source: %w", err)
}
// TLS config that automatically rotates certificates
return tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeAny()), nil
}
# Install Istio with ambient mode (no sidecars, ztunnel at node level)
istioctl install --set profile=ambient
# Or with sidecar mode (traditional)
istioctl install --set profile=default
# Enable sidecar injection for a namespace
kubectl label namespace payments istio-injection=enabled
# peer-authentication.yaml — enforce mTLS for entire namespace
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: payments
spec:
mtls:
mode: STRICT # Reject all non-mTLS traffic. Never leave on PERMISSIVE in production.
# Step 1: Default deny ALL ingress in namespace
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: payments
spec: {} # Empty spec = deny all
---
# Step 2: Explicitly allow checkout → payment-processor
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: allow-checkout-to-processor
namespace: payments
spec:
selector:
matchLabels:
app: payment-processor
rules:
- from:
- source:
principals:
- "cluster.local/ns/payments/sa/checkout-service" # SPIFFE-based identity
to:
- operation:
methods: ["POST"]
paths: ["/v1/payments"]
# VirtualService: retry + timeout
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: payment-processor
namespace: payments
spec:
hosts:
- payment-processor
http:
- retries:
attempts: 3
perTryTimeout: 2s
retryOn: gateway-error,connect-failure,retriable-4xx
timeout: 10s
route:
- destination:
host: payment-processor
# Prometheus metrics auto-collected: request_total, request_duration_ms, etc.
# Jaeger traces: every request gets a trace ID automatically
# View live traffic between services
istioctl proxy-config log payment-processor-pod --level debug
# Kiali topology graph
kubectl port-forward svc/kiali -n istio-system 20001:20001
Choose Linkerd over Istio for: smaller teams, simpler operational model, better performance, no CRD explosion.
# Install Linkerd
linkerd install --crds | kubectl apply -f -
linkerd install | kubectl apply -f -
# Inject into deployment (or annotate namespace)
kubectl annotate namespace payments linkerd.io/inject=enabled
# Verify mTLS is working
linkerd viz tap deploy/checkout-service -n payments
# Traffic tap shows real-time encrypted traffic
linkerd viz edges deployment -n payments
# Linkerd Server (equivalent to Istio AuthorizationPolicy)
apiVersion: policy.linkerd.io/v1beta3
kind: Server
metadata:
name: payment-processor
namespace: payments
spec:
podSelector:
matchLabels:
app: payment-processor
port: 8080
proxyProtocol: HTTP/2
---
apiVersion: policy.linkerd.io/v1beta3
kind: MeshTLSAuthentication
metadata:
name: checkout-service-authn
namespace: payments
spec:
identities:
- "checkout-service.payments.serviceaccount.identity.linkerd.cluster.local"
---
apiVersion: policy.linkerd.io/v1beta3
kind: AuthorizationPolicy
metadata:
name: checkout-to-processor
namespace: payments
spec:
targetRef:
group: policy.linkerd.io
kind: Server
name: payment-processor
requiredAuthenticationRefs:
- name: checkout-service-authn
kind: MeshTLSAuthentication
group: policy.linkerd.io
NetworkPolicies are the Layer-3/4 firewall — always use them even with a service mesh.
# 1. Default deny all ingress AND egress in namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: payments
spec:
podSelector: {} # applies to ALL pods in namespace
policyTypes:
- Ingress
- Egress
# 2. Allow checkout → payment-processor on port 8080
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-checkout-to-processor
namespace: payments
spec:
podSelector:
matchLabels:
app: payment-processor
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: checkout-service
ports:
- protocol: TCP
port: 8080
# 3. Allow DNS resolution (required for all pods)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: payments
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# Block all HTTP except POST /v1/payments
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: l7-payment-processor
namespace: payments
spec:
endpointSelector:
matchLabels:
app: payment-processor
ingress:
- fromEndpoints:
- matchLabels:
app: checkout-service
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: POST
path: /v1/payments
# WRONG: Secret as environment variable
env:
- name: DB_PASSWORD
value: "supersecret" # visible in pod spec, logs, ps aux
# WRONG: Even from k8s secret (still exposed as env var)
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# CORRECT: Vault Agent Sidecar (secrets never touch etcd)
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-secret-db: "secret/payments/db"
vault.hashicorp.com/role: "checkout-service"
vault.hashicorp.com/agent-inject-template-db: |
{{- with secret "secret/payments/db" -}}
DB_PASSWORD={{ .Data.data.password }}
{{- end }}
# CORRECT: External Secrets Operator (ESO) — syncs from AWS Secrets Manager / GCP Secret Manager
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-secret
namespace: payments
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: DB_PASSWORD
remoteRef:
key: prod/payments/db
property: password
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
audience: vault # audience-bound, not usable for anything else
expirationSeconds: 3600 # short-lived
path: token
User Request
│
▼
Identity-Aware Proxy (IAP / Verified Access)
│ checks:
│ - Identity (Google/OIDC token)
│ - Device trust (MDM-enrolled, cert-based)
│ - Context (IP reputation, time of day)
│
▼ [Allow or Deny]
Backend Service (no direct internet exposure)
# Terraform: AWS Verified Access endpoint
resource "aws_verifiedaccess_endpoint" "internal_api" {
verified_access_group_id = aws_verifiedaccess_group.main.id
endpoint_type = "load-balancer"
attachment_type = "vpc"
load_balancer_options {
load_balancer_arn = aws_lb.internal.arn
port = 443
protocol = "https"
subnet_ids = var.private_subnet_ids
}
security_group_ids = [aws_security_group.verified_access.id]
}
resource "aws_verifiedaccess_trust_provider" "oidc" {
trust_provider_type = "user"
user_trust_provider_type = "oidc"
oidc_options {
issuer = "https://accounts.google.com"
authorization_endpoint = "https://accounts.google.com/o/oauth2/v2/auth"
token_endpoint = "https://oauth2.googleapis.com/token"
client_id = var.oauth_client_id
client_secret = var.oauth_client_secret
scope = "openid email"
}
}
Before deploying any new service:
PeerAuthentication set to STRICT (not PERMISSIVE) in production?deny-all policy exists, explicit allowlist for each route?default-deny-all in namespace, per-service allowlist?| Tool | Purpose |
|---|---|
SPIRE | SPIFFE reference implementation — workload identity |
Istio | Full-featured service mesh — mTLS, traffic management, observability |
Linkerd | Lightweight service mesh — simpler, better performance |
Cilium | eBPF-based CNI — Layer-7 NetworkPolicies, identity-aware routing |
Vault | Secret management — dynamic secrets, lease-based rotation |
External Secrets Operator | Sync secrets from AWS/GCP/Azure into k8s |
OPA/Gatekeeper | Policy enforcement — enforce Zero-Trust rules as admission webhooks |
cert-manager | Automate certificate rotation for mTLS |
kubernetes-patterns — base k8s patterns (Deployments, Services, Ingress)devsecops-patterns — SAST/DAST/OPA policy automationauth-patterns — user authentication (JWT, OAuth2) — different from service identitysupply-chain-security — SBOM, SLSA, Sigstore for artifact trust