Introduction
Zero Trust architecture follows the principle of "never trust, always verify." Unlike traditional perimeter-based models, every request must be authenticated and authorized—even those originating internally. This advanced tutorial walks you through a concrete implementation using Terraform, OPA, and Kubernetes. You will learn to deploy strong identity controls, mTLS encryption, and dynamic policies. The goal is a measurable, automated security posture that addresses modern threats effectively.
Prerequisites
- Kubernetes 1.28+ with a managed cluster
- Terraform 1.6+
- Solid knowledge of RBAC and identity management
- OPA tool installed
- Access to an OIDC provider (e.g., Keycloak or Auth0)
Provisioning Secure Infrastructure
resource "aws_vpc" "zero_trust" {
cidr_block = "10.0.0.0/16"
tags = { Name = "zero-trust-vpc" }
}
resource "aws_security_group" "zt_sg" {
vpc_id = aws_vpc.zero_trust.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}This Terraform code creates an isolated VPC with a security group that permits only inbound HTTPS traffic. It applies the principle of least privilege at the network layer from the start.
OPA Policy for Strict Authorization
package zero_trust
default allow = false
allow {
input.request.method == "GET"
input.request.path == "/api/sensitive"
token := input.request.headers["Authorization"]
jwt.verify(token, "public-key")
claims := jwt.decode(token)
claims.role == "admin"
claims.mfa_verified == true
}This Rego policy systematically verifies the JWT, user role, and MFA status. Any non-compliant request is denied by default.
Kubernetes NetworkPolicy
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: zero-trust-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: kube-system
egress:
- to:
- namespaceSelector:
matchLabels:
name: monitoringThis NetworkPolicy blocks all traffic by default except for explicit flows to system and monitoring namespaces, embodying the Zero Trust model at the cluster level.
mTLS Configuration with Istio
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
spec:
rules:
- from:
- source:
principals: ["cluster.local/ns/default/sa/app-sa"]STRICT mode enforces mTLS between all pods. The AuthorizationPolicy adds a service identity layer by validating the source ServiceAccount.
Token Validation in Go
package main
import (
"fmt"
"github.com/golang-jwt/jwt/v5"
)
func ValidateToken(tokenString string) (bool, error) {
key := []byte("your-secret")
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return key, nil
})
if err != nil || !token.Valid {
return false, err
}
claims := token.Claims.(jwt.MapClaims)
return claims["mfa"] == true, nil
}This Go code validates the JWT and explicitly checks the MFA claim. It serves as the mandatory entry point for every incoming request.
Best Practices
- Always encrypt internal traffic with STRICT mTLS
- Centralize policies in OPA or Cedar
- Log every authorization decision with full traceability
- Automate certificate and key rotation
- Regularly test identity compromise scenarios
Common Mistakes to Avoid
- Leaving overly permissive NetworkPolicies (allow-all)
- Forgetting to verify the MFA attribute in tokens
- Using self-signed certificates in production
- Ignoring access denial logging
Further Reading
Deepen these concepts with our expert training on cloud security and Zero Trust architecture: https://learni-group.com/formations