OPA with Rego rules in config maps

Enforce Open Policy Agent (OPA) policies for more fine-grained access control.

By default, the Gloo Platform external auth service is enabled to use an OPA module. You can create your Rego rules as Kubernetes config maps in the cluster. 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:

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, and that your Kubernetes context is set to the cluster you store your Gloo config in (typically the management cluster). If you have different names, make sure to update the sample configuration files in this guide.

Follow the getting started instructions to:

  1. Set up Gloo Gateway in a single cluster.

  2. Deploy sample apps.

  3. Configure an HTTP listener on your gateway and set up basic routing for the sample apps.

  4. Make sure that the external auth service is installed and running. If not, install the external auth service in your single or multicluster environment.

    kubectl get pods -A -l app=ext-auth-service
    

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.
  1. Create an OPA Rego policy file.

    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
    
    Review the following table to understand this configuration.
    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 is GET; or, 2) the path is exactly /ratings/3 AND the HTTP method is either GET or DELETE.
  2. 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
    
  3. 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-addons
    EOF
    
  4. 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 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 Gateway 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 API key policy

  1. 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.

    curl -vik --resolve www.example.com:80:${INGRESS_GW_IP} http://www.example.com:80/ratings/1
    
    curl -vik --resolve www.example.com:443:${INGRESS_GW_IP} https://www.example.com:443/ratings/1
    

  2. Send the request again, this time along a path that is allowed by the OPA policy, such as GET /ratings/2.

    curl -vik -X GET --resolve www.example.com:80:${INGRESS_GW_IP} http://www.example.com:80/ratings/2
    
    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}}
    
  3. Optional: Clean up the resources that you created.

    kubectl -n bookinfo delete ConfigMap allow-get-users
    kubectl -n bookinfo delete ExtAuthPolicy ratings-opa
    kubectl -n bookinfo delete ExtAuthServer ext-auth-server