Istio is an open source service mesh for managing the different microservices that make up a cloud-native application. Istio provides a mechanism to customize the Envoy configuration generated by Istio Pilot using .

This tutorial shows how Istio’s EnvoyFilter can be configured to include Envoy’s External Authorization filter to delegate authorization decisions to OPA.

This tutorial requires Kubernetes 1.14 or later. To run the tutorial locally, we recommend using in version v1.0+ with Kubernetes 1.14+.

The tutorial also requires Istio v1.8.0 or later. It assumes you have Istio deployed on top of Kubernetes. See Istio’s Quick Start page to get started.

The quick_start.yaml manifest defines the following resources:

  • Kubernetes namespace (opa-istio) for OPA-Envoy control plane components.

  • Kubernetes admission controller in the opa-istio namespace that automatically injects the OPA-Envoy sidecar into pods in namespaces labelled with opa-istio-injection=enabled.

  • OPA configuration file and an OPA policy into ConfigMaps in the namespace where the app will be deployed, e.g., default. The following is the example OPA policy:

    • alice is granted a guest role and can perform a GET request to /productpage.
    • bob is granted an admin role and can perform a GET to /productpage and /api/v1/products.
  1. ```
  2. package istio.authz
  3. import input.attributes.request.http as http_request
  4. import input.parsed_path
  5. default allow = false
  6. allow {
  7. parsed_path[0] == "health"
  8. http_request.method == "GET"
  9. }
  10. allow {
  11. roles_for_user[r]
  12. required_roles[r]
  13. }
  14. roles_for_user[r] {
  15. r := user_roles[user_name][_]
  16. }
  17. required_roles[r] {
  18. perm.method = http_request.method
  19. }
  20. user_name = parsed {
  21. [_, encoded] := split(http_request.headers.authorization, " ")
  22. [parsed, _] := split(base64url.decode(encoded), ":")
  23. }
  24. user_roles = {
  25. "alice": ["guest"],
  26. "bob": ["admin"]
  27. }
  28. role_perms = {
  29. "guest": [
  30. {"method": "GET", "path": "/productpage"},
  31. ],
  32. "admin": [
  33. {"method": "GET", "path": "/productpage"},
  34. {"method": "GET", "path": "/api/v1/products"},
  35. ],
  36. }
  37. ```
  38. OPA is configured to query for the `data.istio.authz.allow` decision. If the response is `true` the operation is allowed, otherwise the operation is denied. Sample input received by OPA is shown below:
  39. ![](/projects/openpolicyagent-0.28-en/5cf07a0029fd3f32bef77129f190b677.svg)
  40. ```
  41. data.istio.authz.allow
  42. ```
  43. ![](/projects/openpolicyagent-0.28-en/283d4c145904938f2e4b83853669d94c.svg)
  44. ```
  45. "attributes": {
  46. "request": {
  47. "http": {
  48. "path": "/productpage",
  49. "headers": {
  50. "authorization": "Basic YWxpY2U6cGFzc3dvcmQ="
  51. }
  52. }
  53. }
  54. }
  55. }
  56. ```
  57. With the input value above, the answer is:
  58. ![](/projects/openpolicyagent-0.28-en/51580f8fbb31eb4eafc68afb33107a09.svg)
  59. ```
  60. true
  61. ```
  62. An example of the complete input received by OPA can be seen [here](https://github.com/open-policy-agent/opa-envoy-plugin/tree/master/examples/istio#example-input).
  63. > In typical deployments the policy would either be built into the OPA container image or it would fetched dynamically via the [Bundle API](https://www.openpolicyagent.org/docs/latest/bundles/). ConfigMaps are used in this tutorial for test purposes.
  1. kubectl label namespace default opa-istio-injection="enabled"
  2. kubectl label namespace default istio-injection="enabled"
  1. kubectl apply -f https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/networking/bookinfo-gateway.yaml

minikube:

  1. export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
  2. export INGRESS_HOST=$(minikube ip)
  3. export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
  4. echo $GATEWAY_URL

minikube (example):

Check that alice can access /productpage BUT NOT /api/v1/products.

  1. curl --user alice:password -i http://$GATEWAY_URL/productpage
  2. curl --user alice:password -i http://$GATEWAY_URL/api/v1/products

Check that bob can access /productpage AND /api/v1/products.

  1. curl --user bob:password -i http://$GATEWAY_URL/productpage
  2. curl --user bob:password -i http://$GATEWAY_URL/api/v1/products

Congratulations for finishing the tutorial !

This tutorial showed how Istio’s can be configured to use OPA as an External authorization service.

This tutorial also showed a sample OPA policy that returns a decision to indicate whether a request should be allowed or not.