Share and distribute Open Policy Agent Bundles with OpenFaaS functions

developer-guy
5 min readNov 24, 2020

One of the features of OpenFaaS is an auto-scaling mechanism. The auto-scaling means is that you can scale up/down your function instances as demand increases. Also, OpenFaaS provides a feature called zero-scale. By enabling this feature, you can scale to zero to recover idle resources is available in OpenFaaS.

Using OpenFaaS as an OPA’s Bundle API, you can have all the features by default with less effort. Also, you can’t have to manage to build/push and deploy phases with your Bundle API.

What you will learn in this post?

In this post we are gonna learn:

What is OPA (Open Policy Agent)?

OPA describes itself as a general-purpose policy engine, for more detail you can look at the official documentation.

OPA’s main goal is to decouple policy decision-making from policy enforcement. When your software needs to make policy decisions it queries OPA and supplies structured data (e.g., JSON) as input. OPA accepts arbitrary structured data as input.

Credit: https://www.magalix.com/blog/introducing-policy-as-code-the-open-policy-agent-opa

How can we deploy OPA co-located with our service?

When it comes to deploying OPA, you have more than one option depending on your specific scenario:

  • As a Go library
  • As a daemon

The recommended way is to run OPA is as a daemon. The reason is that this design increases performance and availability. By default, all of the policy and data that OPA uses to make decisions is kept in-memory for the low-latency and we should colocate OPA and the service to avoid the network latency also.

Credit: https://www.magalix.com/blog/introducing-policy-as-code-the-open-policy-agent-opa

How can OpenFaaS help us with the OPA?

OPA exposes a set of APIs that enable unified, logically centralized policy management which is called “Management API’s”. Think of them as a Control Plane for the OPA instances working as a Data Plane. With the Management API's you can control the OPA instances like enable decision logging, configure the Bundle API, etc.

Let’s focus on Bundle API which is one of the Management API for OPA.

Bundle API’s purpose is to help OPA to load policies across the stack to the OPA instances.OPA can periodically download bundles of policy and data from remote HTTP servers. The policies and data are loaded on the fly without requiring a restart of OPA.

In this demo, we create a serverless function that mimics an OPA’s Bundle API. Simply, this serverless function designed as a plain file server. When OPA’s asks for the policies it basically returns bundles that ready on the filesystem as a response.

Demo

You can find all the details about this demo in the Github repo.

Prerequisites

  • A Kubernetes cluster (kind, minikube, etc.)
  • OpenFaaS CLI
  • Arkade
  • Kubectl
  • KinD

Setup

1. Setup Tools

  • Arkade
$ curl -sLS https://dl.get-arkade.dev | sudo sh
  • KinD
$ arkade get kind
  • Kubectl
$ arkade get kubectl
  • faas-cli
$ arkade get faas-cli

2. Set Up Cluster

You can start a Kubernetes cluster with KinD if you don't have one already

$ arkade get kind
$ kind create cluster

3. Deploy OpenFaaS

  • Install OpenFaaS using Arkade
$ arkade install openfaas
  • Verify Deployment
$ kubectl rollout status -n openfaas deploy/gateway
  • Enable local access to Gateway
$ kubectl port-forward -n openfaas svc/gateway 8080:8080 &

4. Configure faas-cli

  • Access password that available in the basic-auth secret in openfaas namespace
$ PASSWORD=$(kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-password}" | base64 --decode; echo)
  • Login with using the password to Gateway
$ echo -n $PASSWORD | faas-cli login --username admin --password-stdin

5. Deploy Function

  • Go to the functions directory, pull the right template and deploy the function
$ cd functions
$ faas-cli template store pull golang-middleware
$ faas-cli up -f bundle-api.yml

6. Load Images

  • Load images from Docker Hub to the KinD
$ docker image pull openpolicyagent/opa:latest
$ kind load docker-image openpolicyagent/opa:latest
$ docker image pull openpolicyagent/demo-restful-api:0.2
$ kind load docker-image openpolicyagent/demo-restful-api:0.27. Deploy the application
$ cd ../hack/manifests <br>
$ kubectl apply -f deployment.yaml
  • Verify Deployment
$ kubectl rollout status deployment demo-restful-api
  • Enable local access to the application
$ kubectl port-forward svc/demo-restful-api 5000:80 &

Test

Rego is the DSL for the OPA. We can author our policies using the rego.

For this tutorial, our desired policy is:

  • People can see their own salaries (GET /finance/salary/{user} is permitted for {user})
  • A manager can see their direct reports’ salaries (GET /finance/salary/{user} is permitted for {user}’s manager)

Check that Alice can see her own salary

  • This command will succeed because Alice wants to see your own salary.
$ curl --user alice:password localhost:5000/finance/salary/alice

Check that bob CANNOT see charlie’s salary.

  • bob is not charlie’s manager, so the following command will fail.
$ curl --user bob:password localhost:5000/finance/salary/charlie
  • bob is Alice's manager, so the following command will succeed.
$ curl --user bob:password localhost:5000/finance/salary/alice

Acknowledgments

References

--

--

developer-guy

🇹🇷KCD Turkey Organizer🎖Best Sigstore Evangelist🐦SSCS Twitter Community Admin✍️@chainguard_dev Fan📦Container Addict📅Organizer at @cloudnativetr•@devopstr