Problem Statement
Istio PeerAuthentication CRD helps to authenticate the calls between services in the mesh. However, if you want to authenticate the calls from external services, Istio requires a different CRD which is called RequestAuthentication. How can you configure RequestAuthentication CRD to verify EntraID JWT and allow/deny calls?
This CRD helps to authenticate the calls from external services using JWT tokens. This guide will show you how to use RequestAuthentication CRD to authenticate the calls from external services using JWT tokens.
Solution
Few basics:
RequestAuthentication resource configures the Istio proxy with data extracted from a JWT token. The JWT token is extracted from the request header and the data is extracted from the token and stored as filter metadata. The data can be used in the authorization policy to allow or deny the request.
RequestAuthentication and AuthenticationPolicy CRDs:
AuthenticationPolicy CRD is similar to what is used for PeerAuthentication CRD. Since PeerAuthentication CRD is used to authenticate the calls between services in the mesh, the correspoonding AuthenticationPolicy CRD uses source: principals to specify the source of the call. However, RequestAuthentication CRD is used to authenticate the calls from external services, the corresponding AuthenticationPolicy CRD uses source: requestPrincipals to specify the source of the call.
Steps to implement RequestAuthentication CRD to verify EntraID JWT and allow/deny calls are as follows:
- Define 'RequestAuthentication' CRD to specify the JWT token issuer, jwksUri, and the JWT token audience. Change 'x' to your tenant id.
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: reqauth-product-jwt
namespace: aks-istio-ingress
spec:
jwtRules:
- issuer: "https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/"
jwksUri: "https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/discovery/v2.0/keys"
EOF
- Define 'AuthorizationPolicy' CRD to verify JWT claims and allow/deny calls. The 'requestPrincipals' field is used to specify the source of the call. The 'principals' field is used to specify the source of the call in PeerAuthentication CRD. Change 'mytenant' to your tenant name and also change the 'upn' claim to the claim that you want to verify.
You can use the following command to get the upn claim.
az account show --query user.name
kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: authz-product
namespace: aks-istio-ingress
spec:
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["*"]
when:
- key: request.auth.claims[upn]
values: ["admin@mytenant.onmicrosoft.com"]
EOF
For testing this, you can use the following command to get the access token and use it in the curl command to test the call.
export ACCESSTOKEN=$(az account get-access-token --query accessToken --output tsv)
curl http://ingressgateway-ip-address -H "Authorization: Bearer $ACCESSTOKEN"
Replace ingressgateway-ip-address with the IP address of the ingress gateway. You can get the IP address of the ingress gateway using kubectl get svc -n aks-istio-ingress
If you change access token, the call will be denied.
You can optionally enable access logging to see the logs in the ingress gateway pod. The following command will enable access logging.
cat <<EOF | kubectl apply -f -
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: ns-logging-aks-istio-ingress
namespace: aks-istio-ingress
spec:
accessLogging:
- providers:
- name: envoy
EOF
Check logs in the ingress gateway pod.
k logs -n aks-istio-ingress -l app=aks-istio-ingressgateway-external
You should be able to see the logs with failed messages if the access token is not valid.
"GET / HTTP/1.1" 403 - rbac_access_denied_matched_policy[none]"
For successful calls, you should see the logs with success messages.
"GET / HTTP/1.1" 404 NR route_not_found -
or if the call is made to a valid endpoint, you should see the logs with success messages.
"GET /productpage HTTP/1.1" 200 - via_upstream
For detailed examples and steps, please refer to the following links:
https://github.com/srinman/aksworkshop/blob/main/lab-istio/istio-security.md
https://istio.io/latest/docs/tasks/security/authorization/authz-jwt/