External Authorization

Overview

External authorization allows offloading authorization of incoming HTTP requests to a remote endpoint not necessarily running inside the proxy’s context. Proxies supporting external authorization will, for every request, issue a permission check to the remote endpoint. Due to the potential high number of RPS a system can have, external authorization has a number of tuneable settings to allow more or less control at the expense of performance (send HTTP payload or headers only, timeout, default behaviour if authorization fails to reply, etc.).

OSM allows configuring envoy’s External Authorization extension through OSM’s MeshConfig.

Limitations

Currently, authorization filtering can’t be dynamically configured to be installed in subsets or groups of proxies defined by the user, and is instead globally applied for all services in the mesh when enabled.

Similarly, the filtering direction is to be statically applied to inbound and ingress connections within the mesh, affecting any and all HTTP request made towards any service or application in the mesh when enabled.

OSM with OPA plugin external authorization walkthrough

The following section will document how to configure external authorization in conjunction with opa-envoy-plugin.

We strongly suggest to go through OPA envoy plugin’s documentation first to further understand their configuration options and deployment models.

The following example uses a single, remote (over the network) endpoint to validate all traffic. This configuration is not recommended for a production deployment.

  • First, start by deploying OSM’s Demo. We will use this sample deployment to test external authorization capabilities. Please refer to OSM’s Automated Demo and follow the instructions.
  1. # Assuming OSM repo is available
  2. cd <PATH_TO_OSM_REPO>
  3. demo/run-osm-demo.sh # wait for all services to come up
  • When OSM’s demo is up and running, proceed to deploy opa-envoy-plugin. OSM provides a curated standalone opa-envoy-plugin deployment chart which exposes opa-envoy-plugin‘s gRPC port (default 9191) through a service, over the network. This is the endpoint that OSM will configure the proxies with when enabling external authorization. The following snippet creates an opa namespace and deploys opa-envoy-plugin in it with minimal deny-all configuration:
  1. kubectl create namespace opa
  2. kubectl apply -f https://raw.githubusercontent.com/openservicemesh/osm-docs/release-v1.0/manifests/opa/deploy-opa-envoy.yaml
  • Once OSM’s demo is up and running, proceed to edit OSM’s MeshConfig to add external authorization to the mesh. For that, configure the inboundExternalAuthorization to point to the remote external authorization endpoint as follows:
  1. kubectl edit meshconfig osm-mesh-config -n osm-system
  2. ## <scroll to the following section>
  3. ...
  4. inboundExternalAuthorization:
  5. enable: true
  6. address: opa.opa.svc.cluster.local
  7. port: 9191
  8. failureModeAllow: false
  9. statPrefix: inboundExtAuthz
  10. timeout: 1s
  11. ...
  • After this step, OSM should configure all proxies to rely on the external authorization service for authorization decisions. By default, the configuration provided with opa-envoy-plugin will deny all requests to any sercices in the mesh. This can be checked on the logs for any of the services on the network, 403 Forbidden whould be expected:
  1. kubectl logs <bookbuyer_pod> -n bookbuyer bookbuyer
  1. ...
  2. --- bookbuyer:[ 8 ] -----------------------------------------
  3. Fetching http://bookstore.bookstore:14001/books-bought
  4. Request Headers: map[Client-App:[bookbuyer] User-Agent:[Go-http-client/1.1]]
  5. Identity: n/a
  6. Booksbought: n/a
  7. Server: envoy
  8. Date: Tue, 04 May 2021 01:20:39 GMT
  9. Status: 403 Forbidden
  10. ERROR: response code for "http://bookstore.bookstore:14001/books-bought" is 403; expected 200
  11. ...
  • To further verify that external authorization is at work, verify the logs of the opa-envoy-plugin instance. Logs of the instance should contain json blobs which log the evaluation of every request received - key-value result should be present on the authorization decision taken by the configuration fed to the opa-envoy-plugin instance:
  1. kubectl logs <opa_pod_name> -n opa
  2. ...
  3. {"decision_id":"1df154b5-658a-47bf-ac18-be52998605da"
  4. ...
  5. "result":false, // resulting decision
  6. ...
  7. "time":"2021-05-04T01:21:18Z","timestamp":"2021-05-04T01:21:18.1971808Z","type":"openpolicyagent.org/decision_logs"
  8. }
  • Once the previous step is verified, proceed to change the OPA policy configuration to authorize all traffic by default:
  1. kubectl edit configmap opa-policy -n opa
  2. ...
  3. ...
  4. default allow = false

Change the previous line value to true:

  1. default allow = true
  • Finally, restart opa-envoy-plugin. This is a necessary step as the configuration for this deployment is pushed as config, as opposed to the application fetching it.
  1. kubectl rollout restart deployment opa -n opa
  • Verify that requests to bookbuyer service are now being authorized:
  1. --- bookbuyer:[ 2663 ] -----------------------------------------
  2. Fetching http://bookstore.bookstore:14001/books-bought
  3. Request Headers: map[Client-App:[bookbuyer] User-Agent:[Go-http-client/1.1]]
  4. Identity: bookstore-v1
  5. Booksbought: 1087
  6. Server: envoy
  7. Date: Tue, 04 May 2021 02:00:46 GMT
  8. Status: 200 OK
  9. MAESTRO! THIS TEST SUCCEEDED!
  10. Fetching http://bookstore.bookstore:14001/buy-a-book/new
  11. Request Headers: map[]
  12. Identity: bookstore-v1
  13. Booksbought: 1088
  14. Server: envoy
  15. Date: Tue, 04 May 2021 02:00:47 GMT
  16. Status: 200 OK
  17. ESC[90m2:00AMESC[0m ESC[32mINFESC[0m BooksCountV1=21490056 ESC[36mcomponent=ESC[0mdemo ESC[36mfile=ESC[0mbooks.go:167
  18. MAESTRO! THIS TEST SUCCEEDED!

The output of OPA plugin can be re-verified to make sure policy decisions are being taken for each request:

  1. {"decision_id":"3f29d449-7f71-4721-b93c-ad7d375e0f80",
  2. ...
  3. "result":true,
  4. ...
  5. "time":"2021-05-04T02:01:35Z","timestamp":"2021-05-04T02:01:35.816768454Z","type":"openpolicyagent.org/decision_logs"}

This example rule shows how you can use the OPA plugin to enforce authorization policies on network traffic and is not intended for production deployments. For example, enforcing authorization on every HTTP call in this manner adds significant overhead, which can be reduced using the OPA injector. For more information on using OPA, see Open Policy Agent official documentation.