Authorization for groups and list claims
This tutorial walks you through examples to configure the groups-base authorization and the authorization of list-typed claims in Istio.
Before you begin
Read the authorization concept and go through the guide on how to configure Istio authorization.
Read the Istio authentication policy and the related mutual TLS authentication concepts.
Follow the Istio installation guide to install Istio with mutual TLS enabled.
Setup the required namespace and workloads
This tutorial runs in a new namespace called authz-groups-test-ns
,
with two workloads, httpbin
and sleep
, both running with an Envoy sidecar
proxy. The following command sets an environmental variable to store the
name of the namespace, creates the namespace, and starts the two workloads.
Before running the following command, you need to enter the directory
containing the Istio installation files.
Set the value of the
NS
environmental variable toauthz-groups-test-ns
:$ export NS=authz-groups-test-ns
Make sure that the
NS
environmental variable points to a testing-only namespace. Run the following command to delete all resources in the namespace pointed by theNS
environmental variable.$ kubectl delete namespace $NS
Create the namespace for this tutorial:
$ kubectl create ns $NS
Create the
httpbin
andsleep
workloads and deployments:$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n $NS $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n $NS
To verify that
httpbin
andsleep
workloads are running andsleep
is able to reachhttpbin
, run the following curl command:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n"
When the command succeeds, it returns the HTTP code 200.
Configure JSON Web Token (JWT) authentication with mutual TLS
The authentication policy you apply next enforces that a valid JWT is needed to
access the httpbin
workload.
The JSON Web Key Set (JWKS) endpoint defined in the policy must sign the JWT.
This tutorial uses the
JWKS endpoint
from the Istio code base and uses
this sample JWT.
The sample JWT contains a JWT claim with a groups
claim key and a list of
strings, ["group1"
, "group2"
] as the claim value.
The JWT claim value could either be a string or a list of strings; both types
are supported.
Apply an authentication policy to require both mutual TLS and JWT authentication for
httpbin
.$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "authentication.istio.io/v1alpha1" kind: "Policy" metadata: name: "require-mtls-jwt" spec: targets: - name: httpbin peers: - mtls: {} origins: - jwt: issuer: "testing@secure.istio.io" jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.5/security/tools/jwt/samples/jwks.json" principalBinding: USE_ORIGIN EOF
Apply a
DestinationRule
policy onsleep
to use mutual TLS when communicating withhttpbin
.$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: use-mtls-on-sleep spec: host: httpbin.$NS.svc.cluster.local trafficPolicy: tls: mode: ISTIO_MUTUAL EOF
Set the
TOKEN
environmental variable to contain a valid sample JWT.$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.5/security/tools/jwt/samples/groups-scope.jwt -s)
Connect to the
httpbin
workload:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
When a valid JWT is attached, it returns the HTTP code 200.
Verify that the connection to the
httpbin
workload fails when the JWT is not attached:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n"
When no valid JWT is attached, it returns the HTTP code 401.
Configure groups-based authorization
This section creates a policy to authorize the access to the httpbin
workload if the requests are originated from specific groups.
As there may be some delays due to caching and other propagation overhead,
wait until the newly defined authorization policy to take effect.
Run the following command to create a
deny-all
policy in thedefault
namespace. The policy doesn’t have aselector
field, which applies the policy to every workload in the$NS
namespace. Thespec:
field of the policy has the empty value{}
. The empty value means that no traffic is permitted, effectively denying all requests.$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-all spec: {} EOF
Once the policy takes effect, verify that Istio rejected the curl connection to the
httpbin
workload:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
Once the policy takes effect, the command returns the HTTP code 403.
To give read access to the
httpbin
workload, create thehttpbin-viewer
policy that applies to workload with labelapp: httpbin
and allows users ingroup1
to access it withGET
method:$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "httpbin-viewer" spec: selector: matchLabels: app: httpbin rules: - to: - operation: methods: ["GET"] when: - key: request.auth.claims[groups] values: ["group1"] EOF
Wait for the newly defined policy to take effect.
After the policy takes effect, verify the connection to the
httpbin
workload succeeds:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
The HTTP header including a valid JWT with the
groups
claim value of ["group1"
,"group2"
] returns HTTP code 200 since it containsgroup1
.
Configure the authorization of list-typed claims
Istio supports configuring the authorization of list-typed claims.
The example JWT contains a JWT claim with a scope
claim key and
a list of strings, ["scope1"
, "scope2"
] as the claim value.
You may use the gen-jwt
python script
to generate a JWT with other list-typed claims for testing purposes.
Follow the instructions in the gen-jwt
script to use the gen-jwt.py
file.
To allow requests with a JWT including a list-typed
scope
claim with the value ofscope1
, update the policyhttpbin-viewer
with the following command:$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "security.istio.io/v1beta1" kind: "AuthorizationPolicy" metadata: name: "httpbin-viewer" spec: selector: matchLabels: app: httpbin rules: - to: - operation: methods: ["GET"] when: - key: request.auth.claims[scope] values: ["scope1"] EOF
Wait for the newly defined policy to take effect.
After the policy takes effect, verify that the connection to the
httpbin
workload succeeds:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
The HTTP header including a valid JWT with the
scope
claim value of ["scope1"
,"scope2"
] returns HTTP code 200 since it containsscope1
.
Cleanup
After completing this tutorial, run the following command to delete all resources created in the namespace.
$ kubectl delete namespace $NS