OPA
Enforce Open Policy Agent (OPA) policies for more fine-grained access control.If you import or export resources across workspaces, your policies might not apply. For more information, see Import and export policies.
About OPA
OPA is an open source, general-purpose policy engine that you can use to enforce versatile policies in a uniform way across your organization. Compared to a role-based access control (RBAC) authorization system, OPA allows you to create more fine-grained policies. For more information, see the OPA docs.
OPA policies are written in Rego. Based on the older query languages Prolog and Datalog, Rego extends support to more modern document models such as JSON.
Gloo Mesh's OPA integration populates an input
document to use in your OPA policies. The structure of the input
document depends on the context of the incoming request, described in the following table.
OPA input structure | Description |
---|---|
input.check_request |
By default, all OPA policies contain an Envoy Auth Service CheckRequest . This object has all the information that Envoy gathers about the request being processed. You can view the structure of this object in the attributes section of the linked Envoy doc. |
input.http_request |
When processing an HTTP request, Envoy populates this field for convenience. For the structure of this object, see the Envoy HttpRequest docs and proto files. |
input.state.jwt |
If you use OAuth, the token retrieved during the OIDC flow is placed into this field. |
The OPA external auth module can be combined with other external auth modules, such as API keys, to perform additional validation checks on incoming requests. To find an example of how to use API keys and OPA together, see API key and OPA. The following video shows an example of using OAuth and OPA.
Before you begin
- Complete the multicluster getting started guide to set up the following testing environment.
- Three clusters along with environment variables for the clusters and their Kubernetes contexts.
- The Gloo Platform CLI,
meshctl
, along with other CLI tools such askubectl
andistioctl
. - The Gloo management server in the management cluster, and the Gloo agents in the workload clusters.
- Istio installed in the workload clusters.
- A simple Gloo workspace setup.
- Install Bookinfo and other sample apps.
- Make sure that the external auth service is installed and running. If not, install the external auth service.
kubectl get pods --context ${REMOTE_CONTEXT1} -A -l app=ext-auth-service
Configure an external auth policy with OPA
Create the external auth policy with OPA.
-
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 --context ${REMOTE_CONTEXT1} -n bookinfo create configmap allow-get-users --from-file=policy.rego
-
Create an external auth server to use for your policy. The following example refers directly to the default Gloo Mesh external auth service, but you can also use a virtual destination instead. For more information, see External auth server setup.
kubectl --context ${REMOTE_CONTEXT1} 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: $REMOTE_CLUSTER1 name: ext-auth-service namespace: gloo-mesh-addons EOF
-
Create an external auth policy that uses the OPA config map.
When you create the policy with a destination selector, only Kubernetes services can be specified in the
applyToDestination
section. Gloo virtual destinations or Gloo external services are not supported.kubectl --context ${REMOTE_CONTEXT1} apply -f - <<EOF apiVersion: security.policy.gloo.solo.io/v2 kind: ExtAuthPolicy metadata: name: ratings-opa namespace: bookinfo spec: applyToDestinations: - selector: labels: app: ratings config: server: name: ext-auth-server namespace: bookinfo cluster: $REMOTE_CLUSTER1 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 |
---|---|
applyToDestinations |
Configure which destinations to apply the policy to, by using labels. Destinations can be a Kubernetes service, VirtualDestination, or ExternalService. If you do not specify any destinations or routes, the policy applies to all destinations in the workspace by default. If you do not specify any destinations but you do specify a route, the policy applies to the route but to no destinations. |
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 Mesh 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 to true . 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 the allow conditions in the policy. |
Verify the external auth OPA 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.Create a temporary curl pod in the
bookinfo
namespace, so that you can test the app setup. You can also use this method in Kubernetes 1.23 or later, but an ephemeral container might be simpler, as shown in the other tab.- Create the curl pod.
kubectl run -it -n bookinfo --context $REMOTE_CONTEXT1 curl \ --image=curlimages/curl:7.73.0 --rm -- sh
- Send a request to the ratings app.
curl http://ratings:9080/ratings/1 -v
Use the
kubernetes debug
command to create an ephemeral curl container in the deployment. This way, the curl container inherits any permissions from the app that you want to test. If you don't run Kubernetes 1.23 or later, you can deploy a separate curl pod or manually add the curl container as shown in the other tab.kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=reviews -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -v http://ratings:9080/ratings/1
If the output has an error about
EphemeralContainers
, see Ephemeral containers don’t work when testing Bookinfo. - Create the curl pod.
-
Send the request again, this time along a path that is allowed by the OPA policy, such as
GET /ratings/2
.Create a temporary curl pod in the
bookinfo
namespace, so that you can test the app setup. You can also use this method in Kubernetes 1.23 or later, but an ephemeral container might be simpler, as shown in the other tab.- Send a request to the ratings app.
curl -v -X GET http://ratings:9080/ratings/2
- Exit the temporary pod. The pod deletes itself.
exit
Use the
kubernetes debug
command to create an ephemeral curl container in the deployment. This way, the curl container inherits any permissions from the app that you want to test. If you don't run Kubernetes 1.23 or later, you can deploy a separate curl pod or manually add the curl container as shown in the other tab.kubectl --context ${REMOTE_CONTEXT1} -n bookinfo debug -i pods/$(kubectl get pod --context ${REMOTE_CONTEXT1} -l app=reviews -A -o jsonpath='{.items[0].metadata.name}') --image=curlimages/curl -- curl -v -X GET http://ratings:9080/ratings/2
You can reach the ratings app again!
{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
- Send a request to the ratings app.
-
Optional: Clean up the resources that you created.
kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete ConfigMap allow-get-users kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete ExtAuthPolicy ratings-opa kubectl --context $REMOTE_CONTEXT1 -n bookinfo delete ExtAuthServer ext-auth-server