Skip to content

pdebuitlear/opa-envoy-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 

Repository files navigation

Open Policy Agent - Istio/Envoy integration

Attempts to demonstrate support for:

  • JWT authentication for multiple IDPs

  • RBAC on Endpoints for roles defined those JWTs

Pre-requisites

A minimal installation of Istio is required, i.e. IstioD only. Please follow the steps in the Kong Istio Gateway instructions for more on doing a 'minimal' install.

Installation instructions for Kong Istio Gateway

Sidecar injection

The pattern being applied here is sidecar injection into the service pods of the Open Policy Agent Envoy plugin.

Side-car injection][opacity=0%

The MutatingWebhook and Admission-controller objects are concerned with dynamically injecting the OPA Envoy plugin into the PODs, based on labels on the namespace.

Mutating Webhook - (MutatingWebhookConfiguration)

The Mutating Webhook resource is watching namespaces with the opa-istio-injection label

    namespaceSelector:
      matchLabels:
        opa-istio-injection: enabled

Within namespaces that match that label, it is looking for pods that have been created (TODO: this could be updated to inject for PODs that have been updated also?)

    rules:
      - operations: ["CREATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]

For pods that meet that criteria, the MutatingWebhook resource then calls into the the web hook(admission-controller) in the opa-istio namespace

    clientConfig:
      service:
        name: admission-controller
        namespace: opa-istio
        path: "/v0/data/istio/inject"

See the MutatingWebhookConfiguration Kubernetes docs for more detail on this functionality

Web hook/admission-controller

The admission-controller deployment in the opa-istio namespace is only concerned with injecting the OPA Envoy plugin sidecar container into the Pods that the have met the criteria defined in the MutatingWebhookConfiguration. The configuration of the injected container is determined by the inject.rego file which is mounted in the inject-policy ConfigMap.

E.g.

    opa_container = {
      "image": "openpolicyagent/opa:0.45.0-istio",
      "name": "opa-istio",
      "args": [
        "run",
        "--server",
        "--config-file=/config/config.yaml",
        "--addr=localhost:8181",
        "--diagnostic-addr=0.0.0.0:8282",
        "/policies/policy.rego",
        "/policies/common.rego",
        "/policies/data.json",
      ]
    }

The logic here is also labelling the pod with opa-istio-injection: enabled. This is done so that EnvoyFilter knows which pods have been injected with the OPA sidecar. TODO: review functionality

     {
      "op": "add",
      "path": "/metadata/labels/opa-istio-injection",
      "value": "enabled" }

EnvoyFilter

As per the Istio docs, the EnvoyFilter is concerned with:

providing a mechanism to customize the Envoy configuration generated by Istio Pilot. Use EnvoyFilter to modify values for certain fields, add specific filters, or even add entirely new listeners, clusters, etc.

— Istio docs


In this case this configuration is using the External Authorization HTTP filter. From the docs:

The external authorization filter calls an external gRPC or HTTP service to check whether an incoming HTTP request is authorized or not. If the request is deemed unauthorized, then the request will be denied normally with 403 (Forbidden) response.

— Envoy docs


In the configuration in this repo, the filter is calling into the OPA envoy plugin (side car), to "authorize" the request.

The configuration of the Envoyfilter is only applied to Pods with the opa-istio-injection: enabled label.

  workloadSelector:
    labels:
      opa-istio-injection: enabled

Infrastructure deployment

kubectl apply -f opa-envoy.yaml

Sample application

Sample deployment

kubectl apply -k sample-application -n opa-test

Code walk-through

In the namespace containing the pods to be secured by OPA, there are three files expected in a ConfigMap called opa-policy (see the configMapGenerator in opa-envoy-example\sample-application\kustomization.yaml). These three files contain the OPA policies to be applied to the services in the namespace.

  • policies/common.rego - contains JWT authentication logic, this logic can be configured to authenticate JWTs from multiple IDP Authorisation servers.

  • policies/policy.rego - uses the data from data.json to determine if the role in the JWT has 'permission' to call the requested resource.

  • policies/data.json - is a static definition of the permissions (TODO: should be renamed to roles) and the resources that they are allowed invoke.

The logic in the policy.rego basically:

  • Calls into the common.rego to authenticate the JWT.

  • Extracts the roles/permissions from the 'roles' claim in the JWT.

  • Checks each of those roles and the path requested against the data from the data.json.

  • returns its response to the EnvoyFilter, which either allows/disallows the request to proceed to the service.

Testing locally

Installing CLI

Unit testing

Command to run Unit tests in this repo

cd sample-application/policies
opa test -v policy_test.rego policy.rego common.rego data.json

Required Annotations

kind: Namespace
apiVersion: v1
metadata:
  name: opa-test
  labels:
    istio-injection: enabled
    opa-istio-injection: enabled

Caveats, Limitations,TODOs

  • Having to restart pods that pre-existed OPA deployment

  • Injecting based on Updates to pods

  • Identify edge cases that should be tested, i.e invalid rego, etc

References

Documentation:

Examples:

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published