The configuration model of authentication and authorization in Ambient Mesh mode is different from that in the original Sidecar mode due to the separation between Layer 4 and Layer 7. This topic describes how to use Layer 7 authorization policies in Service Mesh (ASM) instances of v1.18.
Prerequisites
An ingress gateway and related applications are deployed, and basic features are verified. For more information, see Prerequisites and Step 1 in Getting started.
Limits
The following limits are applicable to authorization policies in a waypoint proxy:
The
action
field cannot be set toCUSTOM
, which indicates that a waypoint proxy does not support custom authorization services.ipBlocks
is not supported in thesource
field.
If a waypoint proxy is deployed, a corresponding ztunnel allows all requests from the waypoint proxy to pass through. In this case, authorization policies must be bound to the waypoint proxy.
Preparations
Run the following command to deploy a waypoint proxy for the productpage service:
istioctl x waypoint apply --service-account bookinfo-productpage
Run the following command to view the pod of the waypoint proxy:
kubectl get pod --show-labels | grep waypoint
Expected output:
bookinfo-productpage-istio-waypoint-6c579dd48d-l**** 1/1 Running 0 91s gateway.istio.io/managed=istio.io-mesh-controller,istio.io/gateway-name=bookinfo-productpage,pod-template-hash=6c579dd48d,service.istio.io/canonical-name=bookinfo-productpage-istio-waypoint,service.istio.io/canonical-revision=latest,sidecar.istio.io/inject=false
Example 1: If a waypoint proxy is deployed for the productpage service, the authorization policy on ztunnels does not take effect.
If a waypoint proxy is deployed for the productpage service, the corresponding ztunnels allow all traffic from the waypoint proxy of the productpage service to pass through. In this case, if an authorization policy is applied to a ztunnel (an application pod is selected by the selector
of the authorization policy), the authorization policy does not take effect.
Use the following content to create a productpage-viewer.yaml file.
The following authorization policy applies to the corresponding ztunnel and prohibits access to port 9080 of the productpage service.
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: app: productpage action: DENY rules: - to: - operation: ports: - "9080"
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create an authorization policy:
kubectl apply -f productpage-viewer.yaml
Run the following commands to perform access tests:
# You can see from the following four tests that the rule to deny access to port 9080 does not work at all. kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title> kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage" | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title> kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title> kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title>
The preceding tests and the tests in Example 2: Prohibit access to port 9080 of the productpage service (no waypoint proxy is deployed) use the same authorization policy. However, all accesses to port 9080 of the productpage service were successful in the preceding tests.
The preceding results show that after you deploy a waypoint proxy, all authorization policies on the ztunnel become invalid. You must change the configuration of the
selector
field to the waypoint proxy for the productpage service.Change the productpage-viewer.yaml file to the following content and run the
kubectl apply -f productpage-viewer.yaml
command to deploy the authorization policy.The following YAML file changes the configuration of the
selector
field.apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage action: DENY rules: - to: - operation: ports: - "9080"
Run the following commands to perform access tests:
# The rule to deny access to port 9080 takes effect. kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" # Expected output: RBAC: access denied% kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage" # Expected output: RBAC: access denied% kubectl exec deploy/sleep -- curl -s http://productpage:9080/ # Expected output: RBAC: access denied% kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ # Expected output: RBAC: access denied%
The error message returned here is
RBAC: access denied%
, which is different from that in Example 2: Prohibit access to port 9080 of the productpage service in the "Layer 4 authentication and authorization" topic. This error is actually returned by the waypoint proxy of the productpage service. When the waypoint proxy finds that access to port 9080 is refused, it returns an HTTP RBAC error with the HTTP 403 status code.Run the following command to remove the authorization policy:
kubectl delete authorizationpolicy productpage-viewer
Example 2: Prohibit the IP address of the sleep pod from accessing the productpage service directly or indirectly through the gateway
Currently, authorization policies configured on a waypoint proxy do not support the ipBlocks
field, and only support the remoteIpBlocks
field. You can configure the remoteIpBlocks
field to match requests only if the requests pass through the gateway. Therefore, you can only prohibit the IP address of the sleep pod from accessing the productpage service through the gateway. You cannot prohibit the IP address of the sleep pod from accessing the productpage service directly.
Create a productpage-viewer.yaml file with the following content to prohibit the sleep pod from accessing the productpage service through the gateway:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage action: DENY rules: - from: - source: remoteIpBlocks: - "${sleep Pod IP}"
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create an authorization policy:
kubectl apply -f productpage-viewer.yaml
Run the following commands to perform access tests:
# The sleep pod is prohibited from accessing the productpage service through the gateway. kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" # Expected output: RBAC: access denied% kubectl exec deploy/sleep -- curl -s http://productpage:9080/ -I # Expected output: HTTP/1.1 200 OK content-type: text/html; charset=utf-8 content-length: 1683 server: istio-envoy date: Tue, 15 Aug 2023 02:11:30 GMT x-envoy-upstream-service-time: 3
The expected output indicates that the sleep pod can directly access the productpage service and cannot access it through the gateway.
Run the following command to remove the authorization policy:
kubectl delete authorizationpolicy productpage-viewer
Example 3: Prohibit access to the productpage service from the pods in the istio-system namespace
Use the following content to create a productpage-viewer.yaml file that prohibits the pods in the istio-system namespace from accessing the productpage service:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage action: DENY rules: - from: - source: namespaces: - istio-system
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create an authorization policy:
kubectl apply -f productpage-viewer.yaml
Run the following commands to perform access tests:
# The gateway cannot access the productpage service. kubectl exec deploy/sleep -- curl -s "http://$GATEWAY_HOST/productpage" # Expected output: RBAC: access denied% kubectl exec deploy/notsleep -- curl -s "http://$GATEWAY_HOST/productpage" # Expected output: RBAC: access denied% kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title> kubectl exec deploy/notsleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title>
The expected output indicates that neither the sleep application nor the notsleep application can access the productpage service through the gateway, but they can directly access the productpage service. This is because the gateway is in the istio-system namespace.
Run the following command to remove the authorization policy:
kubectl delete authorizationpolicy productpage-viewer
Example 4: Implement authentication and authorization based on the JWT that is carried in a request
To implement authentication and authorization based on the JSON Web Token (JWT) carried in a request, you must configure both a request authentication policy and an authorization policy. In this example, requests from the istio-system namespace must carry a valid JWT, and requests from the default namespace do not need to carry a valid JWT. After the configuration is complete, requests that pass through the gateway must carry a valid JWT. The sleep and notsleep applications do not need to carry a valid JWT if they directly access the productpage service.
Create a request authentication policy.
Use the following content to create a jwt-example.yaml file:
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage jwtRules: - issuer: "testing@secure.istio.io" jwks: '{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}'
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create a request authentication policy:
kubectl apply -f jwt-example.yaml
Create an authorization policy.
Use the following content to create a productpage-viewer.yaml file:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage action: ALLOW rules: - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] namespaces: ["istio-system"] - source: namespaces: ["default"]
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create an authorization policy:
kubectl apply -f productpage-viewer.yaml
Run the following command to register the token as an environment variable:
export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg
Run the following commands to perform access tests:
# Access to the productpage service through the gateway without a JWT is prohibited. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage # Expected output: RBAC: access denied% # Direct access to the productpage service without carrying a JWT is allowed. kubectl exec deploy/sleep -- curl -s http://productpage:9080/ | grep -o "<title>.*</title>" # Expected output: <title>Simple Bookstore App</title> # Carry the valid JWT and access the productpage service through the gateway. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Authorization: Bearer $TOKEN" -I # Expected output: HTTP/1.1 200 OK content-type: text/html; charset=utf-8 content-length: 5290 server: istio-envoy date: Tue, 15 Aug 2023 03:16:21 GMT x-envoy-upstream-service-time: 21 # Carry an invalid JWT and access the productpage service through the gateway. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Authorization: Bearer wrongtoken" -I # Expected output: HTTP/1.1 401 Unauthorized www-authenticate: Bearer realm="http://istio-ingressgateway.istio-system/productpage", error="invalid_token" content-length: 79 content-type: text/plain date: Tue, 15 Aug 2023 03:17:26 GMT server: istio-envoy x-envoy-upstream-service-time: 0
Run the following commands to remove the authorization policy and request authentication policy:
kubectl delete authorizationpolicy productpage-viewer kubectl delete requestauthentication jwt-example
Example 5: Prohibit requests whose host is test.com to access port 9080 of the productpage service
Port 9080 of the productpage service is exposed for access. In this example configuration, requests whose host
field is test.com
are not allowed to access port 9080 of the productpage service, and other requests are allowed to access this port.
Use the following content to create a productpage-viewer.yaml file:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage action: DENY rules: - to: - operation: hosts: ["test.com"] ports: ["9080"]
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create an authorization policy:
kubectl apply -f productpage-viewer.yaml
Run the following commands to perform access tests:
# Use test.com as the host to access the productpage service. The access fails. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Host: test.com" # Expected output: RBAC: access denied% # Use test1.com as the host to access the productpage service. The access is successful. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -H "Host: test1.com" -I # Expected output: HTTP/1.1 200 OK content-type: text/html; charset=utf-8 content-length: 5290 server: istio-envoy date: Tue, 15 Aug 2023 03:39:29 GMT x-envoy-upstream-service-time: 18
Run the following command to remove the authorization policy:
kubectl delete authorizationpolicy productpage-viewer
Example 6: Prohibit the use of the HEAD method to access the /productpage path
Use the following content to create a productpage-viewer.yaml file:
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: productpage-viewer namespace: default spec: selector: matchLabels: istio.io/gateway-name: bookinfo-productpage action: DENY rules: - to: - operation: methods: ["HEAD"] paths: ["/productpage"]
Use kubectl to connect to the ASM instance based on the information in the kubeconfig file, and then run the following command to create an authorization policy:
kubectl apply -f productpage-viewer.yaml
Run the following commands to perform access tests:
# Use the HEAD method to access the /productpage path. The default method for the -I option is the HEAD method. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -I # Expected output: HTTP/1.1 403 Forbidden content-length: 19 content-type: text/plain date: Tue, 15 Aug 2023 03:59:37 GMT server: istio-envoy x-envoy-upstream-service-time: 0 # Use the GET method to access the /productpage path. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/productpage -XGET -I # Expected output: HTTP/1.1 200 OK content-type: text/html; charset=utf-8 content-length: 5290 server: istio-envoy date: Tue, 15 Aug 2023 04:00:48 GMT x-envoy-upstream-service-time: 20 # Use the HEAD method to access the /api/v1/products path. kubectl exec deploy/sleep -- curl -s http://$GATEWAY_HOST/api/v1/products -I # Expected output: HTTP/1.1 200 OK content-type: application/json content-length: 395 server: istio-envoy date: Tue, 15 Aug 2023 04:02:39 GMT x-envoy-upstream-service-time: 2
Run the following command to remove the authorization policy:
kubectl delete authorizationpolicy productpage-viewer