Enforce Policy using Open Policy Agent

Open Policy Agent (OPA) Plugin

EnRoute integrates with Open Policy Agent (OPA) to enforce policy on the incoming request.

Enforcing policy using OPA provides clear separation of policy without embedding it in code.

OPA integration is achieved using a plugin in EnRoute. Attaching the OPA plugin to a GatewayHost results in enforcing policy for the application associated with the GatewayHost

  1 # Please edit the object below. Lines beginning with a '#' will be ignored,
  2 # and an empty file will abort the edit. If an error occurs while saving this file will be
  3 # reopened with the relevant failures.
  4 #
  5 apiVersion: enroute.saaras.io/v1
  6 kind: GatewayHost
  7 metadata:
  8   annotations:
  9     meta.helm.sh/release-name: httpbin-service-policy
 10     meta.helm.sh/release-namespace: httpbin
 11   creationTimestamp: "2022-06-14T21:41:41Z"
 12   generation: 8
 13   labels:
 14     app: httpbin
 15     app.kubernetes.io/managed-by: Helm
 16   name: httpbin-80-gatewayhost
 17   namespace: httpbin
 18   resourceVersion: "28424"
 19   uid: 0c75146f-9c37-4285-a3f3-44f22f793635
 20 spec:
 21   routes:
 22   - conditions:
 23     - prefix: /
 24     filters:
 25     - name: httpbin-80-rl2
 26       type: route_filter_ratelimit
 27     services:
 28     - healthCheck:
 29         healthyThresholdCount: 3
 30         host: hc
 31         intervalSeconds: 5
 32         path: /
 33         timeoutSeconds: 4
 34         unhealthyThresholdCount: 3
 35       name: httpbin
 36       port: 80
 37   virtualhost:
 38     filters:
 39     - name: httpbin-80-luatestfilter
 40       type: http_filter_lua
 41     - name: extauthz-filter
 42       type: http_filter_extauthz
 43     fqdn: '*'

Quick Introduction to OPA

The root of OPA evaluation tree is a query that evaluates a chain of OPA rules. OPA rules are defined in a namespaced OPA module.

Here is a simple example of OPA module defined in package opa.auth -

     package envoy.authz

     import input.attributes.request.http as http_request

     default allow = false

     allow {
         action_allowed
     }

     action_allowed {
         http_request.method == "POST"
         startswith(http_request.path, "/post")
     }

Query

# Query rooted at ```envoy.authz.allow``` 
envoy.authz.allow

The OPA Section on Policy Evaluation describes this in more detail.

OPA System Diagram

EnRoute OPA
  • On an incoming request, Envoy makes a request to get a policy decision
  • OPA evaluates policy and returns a result

OPA Filter Configuration

OPA Filter Config for Kubernetes
---
apiVersion: enroute.saaras.io/v1
kind: HttpFilter
metadata:
  name: extauthz-filter
  namespace: httpbin
spec:
  httpFilterConfig:
    config: |
      {
          "auth_service" : "enroutedemo.opa-svc",
          "auth_service_port" : 9191,
          "auth_service_proto" : "grpc",
          "body_max_bytes" : 4096,
          "body_allow_partial" : true,
          "status_on_error" : 403,
          "failure_mode_allow" : true,
          "timeout" : 10,
          "path_prefix" : "",
          "pack_raw_bytes" : false,
      }
  name: extauthz-filter
  type: http_filter_extauthz

Notes

OPA is an enterprise plugin