OPA
Enforce Open Policy Agent (OPA) policies for more fine-grained access control.
This feature is an Enterprise-only feature that requires a Gloo Gateway Enterprise license.
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. For an overview of OPA, review the following video.
OPA input structure
Gloo Gateway’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. For more information about input documents, see the OPA docs.
| 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. |
Before you begin
Get the external address of the gateway and save it in an environment variable.
Setup
Create a Rego rule.
cat <<EOF > policy.rego package test default allow = false allow { startswith(input.http_request.path, "/anything") input.http_request.method == "GET" } allow { input.http_request.path == "/status/200" any({input.http_request.method == "GET", input.http_request.method == "DELETE" }) } EOFReview the following table to understand this configuration.
Setting Description default allow = falseDenies all requests by default. allow {...}Allows requests that match two conditions as follows: 1) The path starts with /anythingAND the HTTP method isGET; or, 2) the path is exactly/status/200AND the HTTP method is eitherGETorDELETE.If you decide to modify the policy example and add in your own allow rules, make sure to also use thepackage testvalue in your policy.Store the OPA policy in a Kubernetes config map.
kubectl -n httpbin create configmap allow-get-users --from-file=policy.regoCreate an AuthConfig resource and add your external authentication rules. The following example configures OPA authentication with the Rego rules that you created earlier.
kubectl apply -f - <<EOF apiVersion: enterprise.gloo.solo.io/v1 kind: AuthConfig metadata: name: opa-auth namespace: httpbin spec: configs: - opaAuth: modules: - name: allow-get-users namespace: httpbin query: "data.test.allow == true" EOFReview the following table to understand this configuration.
Setting Description opaAuthConfigure the OPA authentication details. modulesRefer to the name and namespace of the config map that has the OPA policy. Then, Gloo Gateway can use the OPA policy to use to resolve the query. This example uses the config map that you previously created. queryThe 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 truemeans that the request is authorized. Any other value or error means that the request is denied. In this example,data.test.allowis set totrue.datais the section in the config map.test.alloware part of the OPA policy that you previously created. Access is allowed only if the response meets the allow conditions in the policy.Create a RouteOption resource that refers to the AuthConfig resource that you just created.
kubectl apply -f- <<EOF apiVersion: gateway.solo.io/v1 kind: RouteOption metadata: name: opa-auth namespace: httpbin spec: options: extauth: configRef: name: opa-auth namespace: httpbin EOFCreate an HTTPRoute resource for the httpbin app that requires authentication for requests on the
extauth.exampledomain.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin-opa-auth namespace: httpbin spec: parentRefs: - name: http namespace: gloo-system hostnames: - extauth.example rules: - filters: - type: ExtensionRef extensionRef: group: gateway.solo.io kind: RouteOption name: opa-auth backendRefs: - name: httpbin port: 8000 EOFSend a request to the httpbin app on the
extauth.exampledomain for a path that is not allowed by the OPA policy. Verify that your request is denied and that you get back a 403 HTTP response code.Example output:
* Mark bundle as not supporting multiuse < HTTP/1.1 403 Forbidden < date: Wed, 05 Jun 2024 14:12:36 GMT < server: envoy < content-length: 0Send another request to the httpbin app. This time, you include the
/status/200path that is allowed in the OPA policy. Verify that the request succeeds and that you get back a 200 HTTP response code.Example output:
* Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < access-control-allow-credentials: true < access-control-allow-origin: * < date: Wed, 05 Jun 2024 14:18:28 GMT < content-length: 0 < x-envoy-upstream-service-time: 1 < server: envoy
Cleanup
You can optionally remove the resources that you set up as part of this guide.
kubectl delete authconfig opa-auth -n httpbin
kubectl delete routeoption opa-auth -n httpbin
kubectl delete httproute httpbin-opa-auth -n httpbin
kubectl delete configmap allow-get-users -n httpbin
rm policy.rego