Implement Istio security policies with authorization and authentication for Kubernetes service mesh

Advanced 45 min Apr 07, 2026 20 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure Istio service mesh security with mTLS authentication, JWT validation, and RBAC authorization policies. This tutorial covers implementing comprehensive security controls for microservices communication in production Kubernetes environments.

Prerequisites

  • Kubernetes cluster with admin access
  • Istio service mesh installed
  • kubectl configured
  • Basic understanding of Kubernetes networking

What this solves

Istio security policies provide essential authentication and authorization controls for microservices running in Kubernetes clusters. This tutorial demonstrates how to implement mutual TLS (mTLS) for secure service-to-service communication, configure JWT-based authentication for external access, and establish role-based access control (RBAC) policies to restrict service interactions based on identity and context.

Prerequisites

Before implementing Istio security policies, ensure you have a working Kubernetes cluster with Istio installed. You'll also need kubectl access and basic understanding of Kubernetes concepts like namespaces, services, and pods.

Note: This tutorial builds upon a basic Istio installation. If you need to install Istio first, refer to our Istio installation guide.

Step-by-step configuration

Verify Istio installation and create test namespace

First, verify your Istio installation is working and create a dedicated namespace for testing security policies.

kubectl get pods -n istio-system
kubectl create namespace production
kubectl label namespace production istio-injection=enabled

Deploy sample applications for testing

Deploy a simple application stack to demonstrate Istio security policies in action.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: production
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
      version: v1
  template:
    metadata:
      labels:
        app: frontend
        version: v1
    spec:
      containers:
      - name: frontend
        image: nginx:1.24
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
  namespace: production
spec:
  selector:
    app: frontend
  ports:
  - port: 80
    targetPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
  namespace: production
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
      version: v1
  template:
    metadata:
      labels:
        app: backend
        version: v1
    spec:
      containers:
      - name: backend
        image: httpd:2.4
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: backend
  namespace: production
spec:
  selector:
    app: backend
  ports:
  - port: 80
    targetPort: 80
kubectl apply -f frontend-app.yaml

Configure Istio mTLS authentication policies

Enable automatic mutual TLS for all services in the production namespace. This ensures all service-to-service communication is encrypted and authenticated.

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: production
spec:
  mtls:
    mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: default
  namespace: production
spec:
  host: "*.production.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
kubectl apply -f mtls-policy.yaml

Create JWT authentication policy for external access

Configure JWT-based authentication for external traffic entering the mesh through the Istio gateway.

apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: jwt-auth
  namespace: production
spec:
  selector:
    matchLabels:
      app: frontend
  jwtRules:
  - issuer: "https://accounts.google.com"
    jwksUri: "https://www.googleapis.com/oauth2/v3/certs"
    audiences:
    - "example.com"
  - issuer: "https://auth.example.com"
    jwks: |
      {
        "keys": [
          {
            "kty": "RSA",
            "use": "sig",
            "kid": "example-key-id",
            "n": "example-modulus",
            "e": "AQAB"
          }
        ]
      }
    audiences:
    - "api.example.com"
kubectl apply -f jwt-policy.yaml

Implement RBAC authorization policies

Create fine-grained authorization policies that control which services can communicate based on service identity, HTTP methods, and request paths.

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: frontend-authz
  namespace: production
spec:
  selector:
    matchLabels:
      app: frontend
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"]
  - to:
    - operation:
        methods: ["GET", "POST"]
        paths: ["/api/v1/*"]
    when:
    - key: request.auth.claims[sub]
      values: ["user@example.com"]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: backend-authz
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/production/sa/default"]
        namespaces: ["production"]
  - to:
    - operation:
        methods: ["GET", "POST"]
    when:
    - key: source.labels[app]
      values: ["frontend"]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: deny-all-default
  namespace: production
spec: {}
kubectl apply -f rbac-policy.yaml

Configure service-specific authentication requirements

Create more granular authentication policies for specific services that require different security levels.

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: backend-peer-auth
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  mtls:
    mode: STRICT
  portLevelMtls:
    80:
      mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
  name: backend-request-auth
  namespace: production
spec:
  selector:
    matchLabels:
      app: backend
  jwtRules:
  - issuer: "https://internal-auth.example.com"
    jwksUri: "https://internal-auth.example.com/.well-known/jwks.json"
    audiences:
    - "backend-api.example.com"
    forwardOriginalToken: true
kubectl apply -f service-auth-policy.yaml

Create namespace-level security policies

Implement broader security controls at the namespace level to establish baseline security for all services.

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: namespace-policy
  namespace: production
spec:
  mtls:
    mode: STRICT
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: namespace-authz
  namespace: production
spec:
  rules:
  - from:
    - source:
        namespaces: ["production", "istio-system"]
  - to:
    - operation:
        methods: ["GET", "POST", "PUT", "DELETE"]
    when:
    - key: source.certificate_fingerprint
      notValues: [""]
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: ingress-policy
  namespace: production
spec:
  selector:
    matchLabels:
      app: frontend
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"]
    to:
    - operation:
        methods: ["GET", "POST"]
    when:
    - key: request.headers[authorization]
      notValues: [""]
    - key: source.ip
      values: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
kubectl apply -f namespace-security.yaml

Configure Istio Gateway with security policies

Set up an Istio Gateway with integrated security policies for handling external traffic securely.

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: secure-gateway
  namespace: production
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: example-com-tls
    hosts:
    - "api.example.com"
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "api.example.com"
    tls:
      httpsRedirect: true
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: secure-vs
  namespace: production
spec:
  hosts:
  - "api.example.com"
  gateways:
  - secure-gateway
  http:
  - match:
    - uri:
        prefix: "/api/v1/"
    headers:
      request:
        set:
          x-forwarded-proto: "https"
    route:
    - destination:
        host: frontend.production.svc.cluster.local
        port:
          number: 80
    timeout: 30s
    retries:
      attempts: 3
      perTryTimeout: 10s
kubectl apply -f secure-gateway.yaml

Monitor and troubleshoot Istio security policies

Enable security audit logging

Configure Istio to log security policy decisions for monitoring and troubleshooting purposes.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: security-logging
  namespace: istio-system
spec:
  meshConfig:
    accessLogFile: /dev/stdout
    accessLogEncoding: JSON
    extensionProviders:
    - name: security-audit
      configSource:
        address: "audit-service.logging:8080"
  values:
    pilot:
      env:
        EXTERNAL_ISTIOD: false
        PILOT_ENABLE_WORKLOAD_ENTRY_AUTOREGISTRATION: true
        PILOT_ENABLE_CROSS_CLUSTER_WORKLOAD_ENTRY: true
    global:
      meshConfig:
        defaultConfig:
          proxyStatsMatcher:
            inclusionRegexps:
            - "._cx_."
            - "._rq_."
            - "._rbac_."
kubectl apply -f security-logging.yaml

Set up monitoring dashboards

Configure Prometheus and Grafana to monitor Istio security metrics and policy enforcement.

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/grafana.yaml

Verify your setup

Test your Istio security configuration to ensure policies are working correctly.

kubectl get peerauthentication -n production
kubectl get authorizationpolicy -n production
kubectl get requestauthentication -n production

Test mTLS connectivity

kubectl exec -n production deployment/frontend -c istio-proxy -- openssl s_client -connect backend.production:80 -cert /etc/ssl/certs/cert-chain.pem -key /etc/ssl/private/key.pem -CAfile /etc/ssl/certs/root-cert.pem

Check security policy status

istioctl authn tls-check frontend.production.svc.cluster.local istioctl proxy-config cluster frontend-deployment-pod-name.production --fqdn backend.production.svc.cluster.local

Verify JWT authentication

curl -H "Authorization: Bearer valid-jwt-token" https://api.example.com/api/v1/health
Note: Replace pod names and tokens with actual values from your environment. For comprehensive monitoring, consider implementing our Istio monitoring guide.

Common issues

SymptomCauseFix
RBAC access denied errorsAuthorization policy too restrictiveCheck policy rules with istioctl analyze and verify service identities
mTLS connection failuresCertificate or PeerAuthentication misconfigurationVerify with istioctl authn tls-check and check Envoy config
JWT validation failuresInvalid JWT issuer or JWKS endpointTest JWT manually and verify RequestAuthentication config
Gateway SSL handshake errorsMissing or invalid TLS certificateCheck certificate with kubectl get secret example-com-tls -o yaml
Policy not taking effectSelector labels don't match workloadsVerify pod labels match policy selectors with kubectl get pods --show-labels

Next steps

Automated install script

Run this to automate the entire setup

#istio #kubernetes #service-mesh #security #authentication #authorization #mtls #jwt #rbac

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer