OPA with Rego rules in config maps
Enforce Open Policy Agent (OPA) policies with Rego rules in Kubernetes config maps.
By default, the Gloo external auth service is enabled to use an OPA module. You can create your Rego rules as Kubernetes config maps in the cluster for more fine-grained access control. Then, you use an external auth policy to tell the Gloo external auth service to load these rules via the OPA module. This approach can be convenient for quick testing or small OPA use cases.
Other OPA options:
- You can still load Rego rules with a Kubernetes config map to the Gloo external auth service even when you use other OPA server methods.
- You also get the OPA-Envoy plugin API with the Gloo external auth service.
- Bring your own OPA server for extended OPA capabilities such as bundling.
- Instead of bringing your own server, you can deploy an OPA server as a sidecar to the Gloo external auth service.
If you import or export resources across workspaces, your policies might not apply. For more information, see Import and export policies.
Before you begin
This guide assumes that you use the same names for components like clusters, workspaces, and namespaces as in the getting started. If you have different names, make sure to update the sample configuration files in this guide.
- Set up Gloo Mesh Gateway in a single cluster.
- Install Bookinfo and other sample apps.
Configure an HTTP listener on your gateway and set up basic routing for the sample apps.
Make sure that the external auth service is installed and running. If not, install the external auth service in your Gloo environment.
kubectl get pods -A -l app=ext-auth-service
Get the external address of your ingress gateway. The steps vary depending on the type of load balancer that backs the ingress gateway.
```shell
export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
echo $INGRESS_GW_ADDRESS
```
Note: Depending on your environment, you might see <pending>
instead of an external IP address. For example, if you are testing locally in kind or minikube, or if you have insufficient permissions in your cloud platform, you can instead port-forward the service port of the ingress gateway:
kubectl -n gloo-mesh-gateways port-forward deploy/istio-ingressgateway-1-23 8081
Configure an external auth policy with OPA
Create the external auth policy with OPA.
You can do the following steps in a different order, depending on when you want the policy to take effect. For example, you might want the policy to always take effect as soon as the route is created. To do so, you can create the policy before you add the route to the route table.
Create an OPA Rego policy file.
Review the following table to understand this configuration.cat <<EOF > policy.rego package test default allow = false allow { startswith(input.http_request.path, "/ratings/2") input.http_request.method == "GET" } allow { input.http_request.path == "/ratings/3" any({input.http_request.method == "GET", input.http_request.method == "DELETE" }) } EOF
Setting Description default allow = false
Denies all requests by default. allow {...}
Allows requests that match two conditions as follows. 1) The path starts with /ratings/2
AND the HTTP method isGET
; or, 2) the path is exactly/ratings/3
AND the HTTP method is eitherGET
orDELETE
.Store the OPA policy in a Kubernetes config map in the workload cluster that you want to create the external auth policy in.
kubectl -n bookinfo create configmap allow-get-users --from-file=policy.rego
Create an external auth server to use for your policy.
kubectl apply -f - <<EOF apiVersion: admin.gloo.solo.io/v2 kind: ExtAuthServer metadata: name: ext-auth-server namespace: bookinfo spec: destinationServer: port: number: 8083 ref: cluster: $CLUSTER_NAME name: ext-auth-service namespace: gloo-mesh EOF
Create an external auth policy that uses the OPA config map.
kubectl apply -f - <<EOF apiVersion: security.policy.gloo.solo.io/v2 kind: ExtAuthPolicy metadata: name: ratings-opa namespace: bookinfo spec: applyToRoutes: - route: labels: route: ratings config: server: name: ext-auth-server namespace: bookinfo cluster: $CLUSTER_NAME glooAuth: configs: - opaAuth: modules: - name: allow-get-users namespace: bookinfo query: "data.test.allow == true" EOF
Review the following table to understand this configuration. For more information, see the API reference.
Setting Description applyToRoutes
Use labels to configure which routes to apply the policy to. This example label matches the app and route from the example route table that you apply separately. If omitted and you do not have another selector such as applyToDestinations
, the policy applies to all routes in the workspace.server
The external auth server to use for the policy. opaAuth
Configure the OPA authentication details. modules
Refer to the name and namespace of the config map that has the OPA policy. Then, Gloo can use the OPA policy to use to resolve the query
. This example uses the config map that you previously created.query
The query that determines the authentication decision. The result of this query must be either a boolean or an array with a boolean as the first element. A value of true
means that the request is authorized. Any other value or error means that the request is denied. In this example,data.test.allow
is set totrue
.data
is the section in the config map.test.allow
are part of the OPA policy that you previously created. Access is allowed only if the response meets theallow
conditions in the policy.
Verify the external auth API key policy
Send a request to the
ratings
app along a path that is not allowed by the OPA policy, such as/ratings/1
. Now, the request is blocked with a 403 response.- HTTP:
curl -vik --resolve www.example.com:80:${INGRESS_GW_IP} http://www.example.com:80/ratings/1
- HTTPS:
curl -vik --resolve www.example.com:443:${INGRESS_GW_IP} https://www.example.com:443/ratings/1
- HTTP:
Send the request again, this time along a path that is allowed by the OPA policy, such as
GET /ratings/2
.- HTTP:
curl -vik -X GET --resolve www.example.com:80:${INGRESS_GW_IP} http://www.example.com:80/ratings/2
- HTTPS:
curl -vik -X GET --resolve www.example.com:443:${INGRESS_GW_IP} https://www.example.com:443/ratings/2
You can reach the ratings app again!
{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
- HTTP:
Cleanup
You can optionally remove the resources that you set up as part of this guide.
kubectl -n bookinfo delete ConfigMap allow-get-users
kubectl -n bookinfo delete ExtAuthPolicy ratings-opa
kubectl -n bookinfo delete ExtAuthServer ext-auth-server