Zero-Trust security review for a service — mTLS enforcement, SPIFFE identity, NetworkPolicies, Authorization Policies, east-west traffic, and secret handling.
From clarcnpx claudepluginhub marvinrichter/clarc --plugin clarcPerforms a comprehensive Zero-Trust security review of a Kubernetes service or namespace.
PeerAuthentication mode (STRICT vs PERMISSIVE)Use /zero-trust-review when:
# Check if SPIRE is running
kubectl get pods -n spire
# Verify SVID registration for the service
kubectl exec -n spire spire-server-0 -- \
/opt/spire/bin/spire-server entry show \
-spiffeID spiffe://prod.example.com/ns/NAMESPACE/sa/SERVICE_ACCOUNT
# Check Service Account used by the pod
kubectl get pod POD_NAME -o jsonpath='{.spec.serviceAccountName}'
# Verify token audience binding (projected volumes)
kubectl get pod POD_NAME -o jsonpath='{.spec.volumes[*].projected}'
# Check PeerAuthentication in namespace
kubectl get peerauthentication -n NAMESPACE -o yaml
# Verify mode is STRICT (not PERMISSIVE)
kubectl get peerauthentication -n NAMESPACE -o jsonpath='{.items[*].spec.mtls.mode}'
# For Linkerd: verify mTLS edges
linkerd viz edges deployment -n NAMESPACE
# Check Istio proxy logs for TLS handshake
kubectl logs POD_NAME -c istio-proxy | grep -i "tls\|mtls\|handshake" | tail -20
# List all authorization policies
kubectl get authorizationpolicy -n NAMESPACE -o yaml
# Check for deny-all baseline policy
kubectl get authorizationpolicy deny-all -n NAMESPACE
# Verify each policy uses principals (SPIFFE-based) not just labels
kubectl get authorizationpolicy -n NAMESPACE -o jsonpath='{.items[*].spec.rules[*].from[*].source}'
# List NetworkPolicies
kubectl get networkpolicy -n NAMESPACE -o yaml
# Verify default-deny-all exists
kubectl get networkpolicy default-deny-all -n NAMESPACE
# Check egress rules — should NOT allow 0.0.0.0/0
kubectl get networkpolicy -n NAMESPACE -o jsonpath='{.items[*].spec.egress}'
# For Cilium: check Layer-7 policies
kubectl get ciliumnetworkpolicy -n NAMESPACE -o yaml
# CRITICAL: Find secrets mounted as environment variables
kubectl get pods -n NAMESPACE -o json | \
jq '.items[].spec.containers[].env[]? | select(.valueFrom.secretKeyRef != null) | .name'
# Find secrets from k8s Secret (env-based — should be replaced with Vault/ESO)
kubectl get pods -n NAMESPACE -o json | \
jq '.items[].spec.containers[].envFrom[]? | select(.secretRef != null)'
# Check if Vault Agent or ESO is in use
kubectl get pods -n NAMESPACE -o json | jq '.items[].spec.initContainers[].name'
kubectl get externalsecrets -n NAMESPACE
# Check deployment files for hardcoded secrets (CRITICAL)
grep -r "password\|secret\|token\|key" k8s/ --include="*.yaml" | \
grep -v "secretKeyRef\|secretRef\|ExternalSecret\|vault"
# Istio: find connections NOT using mTLS
kubectl exec -n istio-system prometheus-POD -- \
curl -s 'http://localhost:9090/api/v1/query?query=istio_requests_total{connection_security_policy="none"}' | \
jq '.data.result[] | {source: .metric.source_workload, dest: .metric.destination_workload}'
# Check for services with port named "http" (signals plain HTTP intent)
kubectl get services -n NAMESPACE -o json | \
jq '.items[] | select(.spec.ports[].name == "http") | .metadata.name'
# Linkerd: find unencrypted connections
linkerd viz edges deployment -n NAMESPACE | grep -v "√"
# Verify Istio metrics are flowing
kubectl exec -n monitoring prometheus-POD -- \
curl -s 'http://localhost:9090/api/v1/query?query=istio_requests_total' | \
jq '.data.result | length'
# Check Jaeger for traces
kubectl port-forward -n istio-system svc/tracing 16686:80
# Then open http://localhost:16686
# Verify access logs are enabled
kubectl get meshconfig -n istio-system istio -o jsonpath='{.spec.accessLogFile}'
PeerAuthentication resource — mTLS not configured at alldeny-all AuthorizationPolicy — default allow-all posturePeerAuthentication at PERMISSIVE (acceptable in migration only, with timeline)NetworkPolicy missing default-deny (partial allowlist but no baseline deny)| Status | Condition |
|---|---|
| Approve | No CRITICAL or HIGH issues — STRICT mTLS, deny-all + allowlist, no env-var secrets |
| Warn | Only MEDIUM issues — acceptable with documented remediation plan |
| Block | Any CRITICAL issue — deployment must not proceed |
# 1. Start in PERMISSIVE — verify all services are enrolled in mesh
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: payments
spec:
mtls:
mode: PERMISSIVE
EOF
# 2. Verify all traffic shows as mTLS in Kiali/Prometheus
# 3. Check no plain-HTTP traffic in access logs for 48h
# 4. Switch to STRICT
kubectl patch peerauthentication default -n payments \
--type=json -p='[{"op":"replace","path":"/spec/mtls/mode","value":"STRICT"}]'
# 5. Watch for 503s — plain-HTTP callers will immediately fail
kubectl logs -n payments -l app=payment-processor -c istio-proxy --tail=100 | grep 503
skills/zero-trust-patterns/ — full reference for SPIFFE, Istio, Linkerd, NetworkPoliciesskills/kubernetes-patterns/ — base Kubernetes patternsskills/devsecops-patterns/ — automated security scanning in CI/dep-audit — dependency vulnerability scanningagents/security-reviewer.md — comprehensive security audit/security-review — full DevSecOps scan after zero-trust fixes/tdd — add policy tests for NetworkPolicy and AuthorizationPolicy