Open Policy Agent (OPA) is an extremely powerful tool. It’s quickly becoming one of my favorite tools to use. If you’re not familiar with OPA, I highly recommend checking out this TGIK session about it, or the webinar I took part in for DevOps.com.
OPA is an ecosystem for creating policies as code using a language called Rego. There are multiple runtimes for those policies, including the OPA command line, the Golang Library, and Gatekeeper. In this article I’m going to be focusing on using Rego policies with Fairwinds Insights.
Fairwinds Insights is a software platform to help you manage Kubernetes security, policy, and compliance. It integrates results from many open source tools to help you find opportunities for improvement in your K8s clusters. Some of these opportunities are efficiencies or security related, but here I’m going to focus on the area that I think OPA is best for, organizational specific rules.
Fairwinds Insights can run OPA policies in three different contexts:
To allow for this flexibility, Insights has two different kinds of objects for OPA: Custom Checks and Instances. Custom Checks are basically just the Rego itself. Instances belongs to a particular Custom Check and tell Insights which of the three environments you want to run in, which clusters you want to target, what parameters to pass in, and what kinds of objects to target.
Insights also offers different ways to manage these OPA policies. If you want to control everything through the web interface, you can do that (but some of the information will be in the form of editing YAML in the UI). If you want to call the API directly and insert and delete objects, you can do that (but I don’t recommend it). Or if you want to store your Custom Checks in a Git repo and use the Insights CLI to sync that up to Insights, you can do that too.
The first step is to create our policy. This is going to be the hardest part, because this is not technical step. We need to figure out the business requirement and how we can meet that need.
As an example, let’s say that at Fairwinds we have a rule that every Deployment needs to have a favorite color. Now, how are we going to track the favorite color of a Deployment? Kubernetes offers a few ways that we could handle this; I’m going to go for a simple solution here and say that we’re going to require a label on every deployment. To prevent one team from using color and another using favorite-clr.fairwinds.com as the label, we’ll need to standardize, so we’ll say that each Deployment needs the label of fairwinds.com/color with a value of whatever color that Deployment likes.
Now that we’ve gotten the hard part out of the way, let’s start the easy part, the technical piece. Luckily for me, Insights offers some pre-built policies to start from, and one of them checks if a label exists on a given workload. So all we have to do is swipe that Rego.
Now we need to create an instance; since this is our specific use case, there won’t be any pre-built instance for us to copy. So let’s start building one out.
targets: - apiGroups: - "apps" kinds: - "Deployment" runEnvironments: - "Admission" - "Agent" parameters: labels: - "fairwinds.com/color" blocklist: - "kube-system" - "default"
From top to bottom, the targets say what kinds of objects to target. Since our business rule only applies to Deployments, that’s the only kind of object we want to target. The
runEnvironments says that we want to target the Admission Controller and Agent but not CI. The parameters says that the label we want to require is
fairwinds.com/color and we want to ignore any deployments in
Now that we have all of that together, we can actually apply the policy. I’d prefer to set up a repo and have a CI process that syncs them to Insights, that way any new policies can be reviewed with a PR. But for purposes of this blog post, I’m going to go the quick route and use the UI.
I’ll log in to Insights and click on the policy option on the left nav.
Then click on the Create From Template option. The templates that come up are the same ones that are available in our GitHub repo, so I can select
label-required to start from the Rego that I wanted. I’m going to increase the severity to 0.7, because anything above 0.66 is a danger level and will be blocked by the Admission Controller. Then we need to give the instance a name; I’ll pick
favorite-color-deployments and paste in the YAML we wrote above.
Now let’s click Save Policy and we’re done. The next time the Insights Agent’s OPA job runs, it’ll pick up this new policy, and within a couple hours any installed Admission Controllers I have in this org will pick up this policy and start rejecting Deployments that don’t specify their favorite color. Additionally, if there are already any Deployments in a Namespace other than
default that don’t specify what their favorite color is, then an Action Item will be created in Insights for them.