Security policy examples

Background

This page shows common patterns of using Istio security policies. You may find them useful in your deployment or use this as a quick reference to example policies.

The policies demonstrated here are just examples and require changes to adapt to your actual environment before applying.

Also read the authentication and authorization tasks for a hands-on tutorial of using the security policy in more detail.

Require different JWT issuer per host

JWT validation is common on the ingress gateway and you may want to require different JWT issuers for different hosts. You can use the authorization policy for fine grained JWT validation in addition to the request authentication policy.

Use the following policy if you want to allow access to the given hosts if JWT principal matches. Access to other hosts will always be denied.

  1. apiVersion: security.istio.io/v1
  2. kind: AuthorizationPolicy
  3. metadata:
  4. name: jwt-per-host
  5. namespace: istio-system
  6. spec:
  7. selector:
  8. matchLabels:
  9. istio: ingressgateway
  10. action: ALLOW
  11. rules:
  12. - from:
  13. - source:
  14. # the JWT token must have issuer with suffix "@example.com"
  15. requestPrincipals: ["*@example.com"]
  16. to:
  17. - operation:
  18. hosts: ["example.com", "*.example.com"]
  19. - from:
  20. - source:
  21. # the JWT token must have issuer with suffix "@another.org"
  22. requestPrincipals: ["*@another.org"]
  23. to:
  24. - operation:
  25. hosts: [".another.org", "*.another.org"]

Namespace isolation

The following two policies enable strict mTLS on namespace foo, and allow traffic from the same namespace.

  1. apiVersion: security.istio.io/v1
  2. kind: PeerAuthentication
  3. metadata:
  4. name: default
  5. namespace: foo
  6. spec:
  7. mtls:
  8. mode: STRICT
  9. ---
  10. apiVersion: security.istio.io/v1
  11. kind: AuthorizationPolicy
  12. metadata:
  13. name: foo-isolation
  14. namespace: foo
  15. spec:
  16. action: ALLOW
  17. rules:
  18. - from:
  19. - source:
  20. namespaces: ["foo"]

Namespace isolation with ingress exception

The following two policies enable strict mTLS on namespace foo, and allow traffic from the same namespace and also from the ingress gateway.

  1. apiVersion: security.istio.io/v1
  2. kind: PeerAuthentication
  3. metadata:
  4. name: default
  5. namespace: foo
  6. spec:
  7. mtls:
  8. mode: STRICT
  9. ---
  10. apiVersion: security.istio.io/v1
  11. kind: AuthorizationPolicy
  12. metadata:
  13. name: ns-isolation-except-ingress
  14. namespace: foo
  15. spec:
  16. action: ALLOW
  17. rules:
  18. - from:
  19. - source:
  20. namespaces: ["foo"]
  21. - source:
  22. principals: ["cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"]

Require mTLS in authorization layer (defense in depth)

You have configured PeerAuthentication to STRICT but want to make sure the traffic is indeed protected by mTLS with an extra check in the authorization layer, i.e., defense in depth.

The following policy denies the request if the principal is empty. The principal will be empty if plain text is used. In other words, the policy allows requests if the principal is non-empty. "*" means non-empty match and using with notPrincipals means matching on empty principal.

  1. apiVersion: security.istio.io/v1
  2. kind: AuthorizationPolicy
  3. metadata:
  4. name: require-mtls
  5. namespace: foo
  6. spec:
  7. action: DENY
  8. rules:
  9. - from:
  10. - source:
  11. notPrincipals: ["*"]

Require mandatory authorization check with DENY policy

You can use the DENY policy if you want to require mandatory authorization check that must be satisfied and cannot be bypassed by another more permissive ALLOW policy. This works because the DENY policy takes precedence over the ALLOW policy and could deny a request early before ALLOW policies.

Use the following policy to enforce mandatory JWT validation in addition to the request authentication policy. The policy denies the request if the request principal is empty. The request principal will be empty if JWT validation failed. In other words, the policy allows requests if the request principal is non-empty. "*" means non-empty match and using with notRequestPrincipals means matching on empty request principal.

  1. apiVersion: security.istio.io/v1
  2. kind: AuthorizationPolicy
  3. metadata:
  4. name: require-jwt
  5. namespace: istio-system
  6. spec:
  7. selector:
  8. matchLabels:
  9. istio: ingressgateway
  10. action: DENY
  11. rules:
  12. - from:
  13. - source:
  14. notRequestPrincipals: ["*"]

Similarly, Use the following policy to require mandatory namespace isolation and also allow requests from ingress gateway. The policy denies the request if the namespace is not foo and the principal is not cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account. In other words, the policy allows the request only if the namespace is foo or the principal is cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account.

  1. apiVersion: security.istio.io/v1
  2. kind: AuthorizationPolicy
  3. metadata:
  4. name: ns-isolation-except-ingress
  5. namespace: foo
  6. spec:
  7. action: DENY
  8. rules:
  9. - from:
  10. - source:
  11. notNamespaces: ["foo"]
  12. notPrincipals: ["cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"]