Chuyển đến nội dung chính

LESSON 27: ISTIO SECURITY — AUTHORIZATIONPOLICY AND REQUESTAUTHENTICATION

Configure Istio security: AuthorizationPolicy for access control, RequestAuthentication for JWT validation, network segmentation, and zero-trust security model.

🔒 DevSecOps — Lesson 27 LESSON 27: ISTIO SECURITY — AUTHORIZATIONPOLICY AND REQUESTAUTHENTICATION

Deploy Microservices On-Premises with Kubernetes HA

Part 6: Service Mesh & Ingress with Istio

xdev.asia

🎯 LESSON OBJECTIVE__HTMLTAG_70___
  • ✅ AuthorizationPolicy: ALLOW, DENY, CUSTOM rules
  • ✅ RequestAuthentication: JWT token validation
  • ✅ Network segmentation between namespaces__HTMLTAG_77___
  • ✅ Zero-trust security model
  • ✅ Audit logging for security events__HTMLTAG_81___

PART 1: AUTHORIZATIONPOLICY


Istio Authorization Flow:

Request → Envoy Proxy → AuthorizationPolicy check → Allow/Deny

Policy Actions:
- ALLOW: Explicitly permit (whitelist)
- DENY:  Explicitly block (blacklist)
- CUSTOM: Delegate to external authz

Evaluation Order:
1. CUSTOM policies
2. DENY policies (if match → reject)
3. ALLOW policies (if match → allow)
4. No ALLOW policy → allow all (permissive)
5. Has ALLOW policy but no match → DENY

1.1. Default Deny All (Zero Trust)

# Deny all traffic in namespace:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-all
  namespace: default
spec:
  {}
  # Empty spec = match all → no ALLOW rules → DENY all

1.2. Allow Specific Services__HTMLTAG_89___
# Allow order-service to call payment-service:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-order-to-payment
  namespace: default
spec:
  selector:
    matchLabels:
      app: payment-service
  action: ALLOW
  rules:
    - from:
        - source:
            principals:
              - "cluster.local/ns/default/sa/order-service"
      to:
        - operation:
            methods: ["POST"]
            paths: ["/api/v1/payments/*"]
---
# Allow frontend to call API services:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-frontend-to-api
  namespace: default
spec:
  selector:
    matchLabels:
      app: order-service
  action: ALLOW
  rules:
    - from:
        - source:
            principals:
              - "cluster.local/ns/default/sa/frontend"
      to:
        - operation:
            methods: ["GET", "POST", "PUT"]
            paths: ["/api/v1/*"]
---
# Allow ingress gateway to all services:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-ingress
  namespace: default
spec:
  action: ALLOW
  rules:
    - from:
        - source:
            namespaces: ["istio-system"]

1.3. Deny Specific Patterns

# Block access to admin endpoints from non-admin:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-admin-access
  namespace: default
spec:
  selector:
    matchLabels:
      app: admin-service
  action: DENY
  rules:
    - from:
        - source:
            notNamespaces: ["admin"]
      to:
        - operation:
            paths: ["/admin/*"]
---
# Block specific IP ranges:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: deny-external-ips
  namespace: default
spec:
  action: DENY
  rules:
    - from:
        - source:
            ipBlocks: ["10.0.0.0/8"]
            notIpBlocks: ["10.0.1.0/24"]   # Except trusted subnet

PART 2: JWT AUTHENTICATION

2.1. RequestAuthentication

# Validate JWT tokens:
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
  name: jwt-auth
  namespace: default
spec:
  selector:
    matchLabels:
      app: order-service
  jwtRules:
    - issuer: "https://auth.myapp.com"
      jwksUri: "https://auth.myapp.com/.well-known/jwks.json"
      audiences:
        - "api.myapp.com"
      forwardOriginalToken: true
      outputPayloadToHeader: x-jwt-payload
---
# Require valid JWT:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: default
spec:
  selector:
    matchLabels:
      app: order-service
  action: ALLOW
  rules:
    - from:
        - source:
            requestPrincipals: ["https://auth.myapp.com/*"]
      when:
        - key: request.auth.claims[role]
          values: ["user", "admin"]

2.2. Role-Based Access (JWT Claims)

# Admin-only endpoints:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: admin-only
  namespace: default
spec:
  selector:
    matchLabels:
      app: admin-service
  action: ALLOW
  rules:
    - from:
        - source:
            requestPrincipals: ["https://auth.myapp.com/*"]
      to:
        - operation:
            paths: ["/admin/*"]
      when:
        - key: request.auth.claims[role]
          values: ["admin"]
---
# Read-only for viewers:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: viewer-read-only
  namespace: default
spec:
  selector:
    matchLabels:
      app: order-service
  action: ALLOW
  rules:
    - from:
        - source:
            requestPrincipals: ["https://auth.myapp.com/*"]
      to:
        - operation:
            methods: ["GET"]
      when:
        - key: request.auth.claims[role]
          values: ["viewer"]

PART 3: NAMESPACE SEGMENTATION__HTMLTAG_101___
# Isolate namespaces:
# default  ←→  messaging  (allowed)
# default  ←→  database   (allowed)
# default  ←X→ monitoring (blocked)

# Allow default → messaging:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-from-default
  namespace: messaging
spec:
  action: ALLOW
  rules:
    - from:
        - source:
            namespaces: ["default"]

# Allow default → database:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: allow-from-default
  namespace: database
spec:
  action: ALLOW
  rules:
    - from:
        - source:
            namespaces: ["default"]
    - from:
        - source:
            namespaces: ["monitoring"]
      to:
        - operation:
            methods: ["GET"]
            paths: ["/metrics"]

PART 4: SECURITY AUDIT LOGGING

# Enable access logging:
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: access-logging
  namespace: istio-system
spec:
  accessLogging:
    - providers:
        - name: envoy
      filter:
        expression: "response.code >= 400 || connection.mtls == false"
# View access logs:
kubectl -n default logs order-service-xxx -c istio-proxy | \
  jq 'select(.response_code >= 400)'

# Check mTLS status:
istioctl authn tls-check order-service-xxx.default

# Analyze authorization denials:
kubectl -n default logs order-service-xxx -c istio-proxy | \
  grep "rbac_access_denied"

💡 KEY TAKEAWAYS

  1. Zero Trust: Start with deny-all, explicitly allow needed paths
  2. AuthorizationPolicy: Service-to-service access control (who can call whom)
  3. RequestAuthentication: JWT validation at ingress (end-user auth)
  4. mTLS + AuthZ: Combined = strong identity-based security
  5. Namespace segmentation: Isolate blast radius of compromised services
  6. Audit: Log denied requests, mTLS failures for security monitoring

🎯 EXERCISES

Exercise 1: Zero Trust Lab__HTMLTAG_138___
  • Apply deny-all to default namespace
  • Create ALLOW policies for specific service paths
  • Test: unauthorized service call → RBAC denied

Exercise 2: JWT Auth Lab__HTMLTAG_148___
  • Configure RequestAuthentication with Keycloak
  • Create role-based AuthorizationPolicy
  • Test admin vs viewer access

📚 NEXT POST

In Lesson 28: GitOps with ArgoCD — Architecture and Installation, we will move on to the GitOps workflow for continuous deployment.