This repository contains an extended version of OPA (OPA-Envoy) that allows you to enforce OPA policies with Envoy.
Use GitHub Issues to request features or file bugs.
The OPA-Envoy plugin can be deployed with Envoy-based service meshes such as:
OPA-Envoy extends OPA with a gRPC server that implements the Envoy External Authorization API. You can use this version of OPA to enforce fine-grained, context-aware access control policies with Envoy without modifying your microservice.
More information about the OPA-Envoy plugin including performance benchmarks, debugging tips, detailed usage examples can be found in the OPA documentation.
This section assumes you are testing with Envoy v1.10.0 or later.
-
Start Minikube.
minikube start
-
Install OPA-Envoy.
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/opa-envoy-plugin/main/quick_start.yaml
The
quick_start.yamlmanifest defines the following resources:-
A ConfigMap containing an Envoy configuration with an External Authorization Filter to direct authorization checks to the OPA-Envoy sidecar. See
kubectl get configmap proxy-configfor details. -
OPA configuration file, and an OPA policy into ConfigMaps in the namespace where the app will be deployed, e.g.,
default. -
A Deployment consisting an example Go application with OPA-Envoy and Envoy sidecars. The sample app provides information about employees in a company and exposes APIs to
getandcreateemployees. More information about the app can be found here. The deployment also includes an init container that installs iptables rules to redirect all container traffic through the Envoy proxy sidecar. More information can be found here.
-
-
Make the application accessible outside the cluster.
kubectl expose deployment example-app --type=NodePort --name=example-app-service --port=8080
-
Set the
SERVICE_URLenvironment variable to the service’s IP/port.minikube:
export SERVICE_PORT=$(kubectl get service example-app-service -o jsonpath='{.spec.ports[?(@.port==8080)].nodePort}') export SERVICE_HOST=$(minikube ip) export SERVICE_URL=$SERVICE_HOST:$SERVICE_PORT echo $SERVICE_URL
minikube (example):
192.168.99.100:31380
-
Exercise the sample OPA policy.
For convenience, we’ll want to store Alice’s and Bob’s tokens in environment variables.
export ALICE_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZ3Vlc3QiLCJzdWIiOiJZV3hwWTJVPSIsIm5iZiI6MTUxNDg1MTEzOSwiZXhwIjoxOTQxMDgxNTM5fQ.rN_hxMsoQzCjg6lav6mfzDlovKM9azaAjuwhjq3n9r8" export BOB_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYWRtaW4iLCJzdWIiOiJZbTlpIiwibmJmIjoxNTE0ODUxMTM5LCJleHAiOjE5NDEwODE1Mzl9.ek3jmNLPclafELVLTfyjtQNj0QKIEGrbhKqpwXmQ8EQ"
Check that
Alicecan get employees but cannot create one.curl -i -H "Authorization: Bearer "$ALICE_TOKEN"" http://$SERVICE_URL/people curl -i -H "Authorization: Bearer "$ALICE_TOKEN"" -d '{"firstname":"Charlie", "lastname":"OPA"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
Check that
Bobcan get employees and also create one.curl -i -H "Authorization: Bearer "$BOB_TOKEN"" http://$SERVICE_URL/people curl -i -H "Authorization: Bearer "$BOB_TOKEN"" -d '{"firstname":"Charlie", "lastname":"Opa"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
Check that
Bobcannot create an employee with the same firstname as himself.curl -i -H "Authorization: Bearer "$BOB_TOKEN"" -d '{"firstname":"Bob", "lastname":"Rego"}' -H "Content-Type: application/json" -X POST http://$SERVICE_URL/people
To deploy OPA-Envoy include the following container in your Kubernetes Deployments:
containers:
- image: openpolicyagent/opa:latest-envoy
imagePullPolicy: IfNotPresent
name: opa-envoy
volumeMounts:
- mountPath: /config
name: opa-envoy-config
args:
- run
- --server
- --addr=localhost:8181
- --diagnostic-addr=0.0.0.0:8282
- --config-file=/config/config.yaml
livenessProbe:
httpGet:
path: /health?plugins
port: 8282
readinessProbe:
httpGet:
path: /health?plugins
port: 8282The OPA-Envoy configuration file should be volume mounted into the container. Add the following volume to your Kubernetes Deployments:
volumes:
- name: opa-envoy-config
configMap:
name: opa-envoy-configIn the Quick Start section an OPA policy is loaded via a volume-mounted ConfigMap. For production deployments, we recommend serving policy Bundles from a remote HTTP server.
Using the configuration shown below, OPA will download a sample bundle from https://www.openpolicyagent.org. The sample bundle contains the exact same policy that was loaded into OPA via the volume-mounted ConfigMap.
config.yaml:
services:
- name: controller
url: https://www.openpolicyagent.org
bundles:
envoy/authz:
service: controller
plugins:
envoy_ext_authz_grpc:
addr: :9191 # default `:9191`
path: envoy/authz/allow # default: `envoy/authz/allow`
dry-run: false # default: false
enable-reflection: false # default: false
grpc-max-recv-msg-size: 40194304 # default: 1024 * 1024 * 4
grpc-max-send-msg-size: 2147483647 # default: max Int
skip-request-body-parse: false # default: false
enable-performance-metrics: false # default: false. Adds `grpc_request_duration_seconds` prometheus histogram metric You can download the bundle and inspect it yourself:
mkdir example && cd example
curl -s -L https://www.openpolicyagent.org/bundles/envoy/authz | tar xzvIn this way OPA can periodically download bundles of policy from an external server and hence loading the policy via a
volume-mounted ConfigMap would not be required. The readinessProbe to GET /health?bundles ensures that the opa-envoy
container becomes ready after the bundles are activated.
Dependencies are managed with Modules.
If you need to add or update dependencies, modify the go.mod file or
use go get. More information is available here.
Finally commit all changes to the repository.
Please see the MAINTAINERS.md file for maintainer details.