Authorization with JWT
This task shows you how to set up an Istio authorization policy to enforce access based on a JSON Web Token (JWT). An Istio authorization policy supports both string typed and list-of-string typed JWT claims.
Before you begin
Before you begin this task, perform the following actions:
Read Authorization and Authentication.
Install Istio using Istio installation guide.
Deploy two workloads:
httpbin
andsleep
. Deploy these in one namespace, for examplefoo
. Both workloads run with an Envoy proxy in front of each. Deploy the example namespace and workloads using these commands:$ kubectl create ns foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n foo
Verify that
sleep
successfully communicates withhttpbin
using this command:$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}\n"
200
If you don’t see the expected output, retry after a few seconds. Caching and propagation can cause a delay.
Allow requests with valid JWT and list-typed claims
The following command creates the
jwt-example
request authentication policy for thehttpbin
workload in thefoo
namespace. This policy forhttpbin
workload accepts a JWT issued bytesting@secure.istio.io
:$ kubectl apply -f - <<EOF
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "jwt-example"
namespace: foo
spec:
selector:
matchLabels:
app: httpbin
jwtRules:
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/jwks.json"
EOF
Verify that a request with an invalid JWT is denied:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer invalidToken" -w "%{http_code}\n"
401
Verify that a request without a JWT is allowed because there is no authorization policy:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -w "%{http_code}\n"
200
The following command creates the
require-jwt
authorization policy for thehttpbin
workload in thefoo
namespace. The policy requires all requests to thehttpbin
workload to have a valid JWT withrequestPrincipal
set totesting@secure.istio.io/testing@secure.istio.io
. Istio constructs therequestPrincipal
by combining theiss
andsub
of the JWT token with a/
separator as shown:$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: foo
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
EOF
Get the JWT that sets the
iss
andsub
keys to the same value,testing@secure.istio.io
. This causes Istio to generate the attributerequestPrincipal
with the valuetesting@secure.istio.io/testing@secure.istio.io
:$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode -
{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}
Verify that a request with a valid JWT is allowed:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"
200
Verify that a request without a JWT is denied:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -w "%{http_code}\n"
403
The following command updates the
require-jwt
authorization policy to also require the JWT to have a claim namedgroups
containing the valuegroup1
:$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: foo
spec:
selector:
matchLabels:
app: httpbin
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
when:
- key: request.auth.claims[groups]
values: ["group1"]
EOF
Don’t include quotes in the
request.auth.claims
field unless the claim itself has quotes in it.Get the JWT that sets the
groups
claim to a list of strings:group1
andgroup2
:$ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.8/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode -
{"exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"testing@secure.istio.io","scope":["scope1","scope2"],"sub":"testing@secure.istio.io"}
Verify that a request with the JWT that includes
group1
in thegroups
claim is allowed:$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer $TOKEN_GROUP" -w "%{http_code}\n"
200
Verify that a request with a JWT, which doesn’t have the
groups
claim is rejected:$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -s -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"
403
Clean up
Remove the namespace
foo
:$ kubectl delete namespace foo
See also
Introducing the Istio v1beta1 Authorization Policy
Introduction, motivation and design principles for the Istio v1beta1 Authorization Policy.
App Identity and Access Adapter
Using Istio to secure multi-cloud Kubernetes applications with zero code changes.
Micro-Segmentation with Istio Authorization
Describe Istio’s authorization feature and how to use it in various use cases.
Authorization Policy Trust Domain Migration
Shows how to migrate from one trust domain to another without changing authorization policy.
Authorization for HTTP traffic
Shows how to set up access control for HTTP traffic.
How to set up access control for TCP traffic.