Introduction to Open Policy Agent (OPA) in Kubernetes

Sharon Sahadevan
4 min readFeb 23, 2023

--

Kubernetes is a powerful and very flexible platform for deploying and managing containerized applications, but with great power comes great responsibility. As the number of applications and users in a Kubernetes cluster grows, enforcing security policies and other constraints on cluster resources becomes increasingly important. That’s where Open Policy Agent (OPA) comes in.

OPA is a popular policy engine used in Kubernetes to enforce security policies and other constraints on cluster resources. OPA provides a flexible and extensible way to define policies using declarative language. In addition, it can enforce policies across multiple Kubernetes clusters and other cloud-native environments.

In this article, we’ll introduce the basics of OPA in Kubernetes and provide an example of how to use it to enforce security policies.

What is OPA?

OPA is an open-source project that provides a high-level declarative language called Rego for defining policies. Rego policies can be used to enforce a wide range of constraints on cluster resources, such as:

  • Restricting Access to specific Kubernetes resources or namespaces
  • Enforcing labeling or naming conventions for resources
  • Limiting resource consumption or usage
  • Enforcing security policies, such as encryption or access controls

OPA works by intercepting requests to the Kubernetes API server and evaluating policies before allowing the request to proceed. Policies are defined using Rego, which is designed to be easy to read and write. Rego policies can be used to define complex policies using a modular approach, and it is a flexible and expressive language.

How to use OPA in Kubernetes

OPA can be deployed as a Kubernetes pod, and it integrates with Kubernetes RBAC to control Access to its policies. It can be used with various Kubernetes resources such as deployments, services, and namespaces, and it supports dynamic configuration and reloading of policies.

Here’s an example of how to use OPA to enforce security policies in Kubernetes. In this example, we’ll define a policy restricting Access to a specific namespace based on the user’s email domain.
First, we’ll deploy OPA as a Kubernetes pod using the following YAML file:

apiVersion: v1
kind: ServiceAccount
metadata:
name: opa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: opa
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: opa
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: opa
subjects:
- kind: ServiceAccount
name: opa
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: opa
spec:
selector:
matchLabels:
app: opa
template:
metadata:
labels:
app: opa
spec:
serviceAccountName: opa
containers:
- name: opa
image: openpolicyagent/opa:latest
args:
- "run"
- "--server"
volumeMounts:
- name: config
mountPath: /config
volumes:
- name: config
configMap:
name: opa-policy

We also need to create a ConfigMap that contains the policy that we want to enforce. In this example, the policy is stored in a file called policy.rego. We can create the ConfigMap using the following YAML file:

apiVersion: v1
kind: ConfigMap
metadata:
name: opa-policy
data:
policy.rego: |
package kubernetes.authz

allow = false

# Deny access to the my-namespace namespace for users with a non-whitelisted email domain
deny[msg] {
some email
input.user.email == email
not startswith(email, "whitelisted.com")
input.namespace == "my-namespace"
msg = "Access denied. Users with email domains outside whitelisted.com are not allowed to access the my-namespace namespace."
}

# Allow access to everything else
allow {
not deny[msg]
}

This policy is defined using Rego and is designed to deny access to the my-namespace namespace for users with a non-whitelisted email domain. The policy also allows access to everything else.

To enforce this policy, we can create a ValidatingWebhookConfiguration that sends requests to the OPA pod for evaluation. We can create the ValidatingWebhookConfiguration using the following YAML file:

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: opa-policy
webhooks:
- name: opa.kubernetes.io
namespaceSelector:
matchLabels:
app: opa
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["namespaces"]
clientConfig:
service:
name: opa
namespace: default
path: "/v1/data/kubernetes/authz"
sideEffects: None
admissionReviewVersions: ["v1", "v1beta1"]

This configuration tells Kubernetes to send requests to the OPA pod for validation when a namespace is created or updated.

Now that we have OPA and the policy in place, we can test the policy by creating a new namespace with a user that has a whitelisted email domain:

apiVersion: v1
kind: Namespace
metadata:
name: my-namespace
annotations:
kubernetes.io/enforce-opa: "true"
spec:
finalizers:
- kubernetes

In this example, the kubernetes.io/enforce-opa annotation is set to true to indicate that OPA should be used to validate requests.

If we try to create a namespace with a user that has a non-whitelisted email domain, we’ll get an error:

Error from server: admission webhook "opa.kubernetes.io" denied the request: [Access denied. Users with email domains outside whitelisted.com are not allowed to access the my-namespace namespace.]

This error message indicates that the request was denied because the user has a non-whitelisted email domain.

Conclusion

Open Policy Agent (OPA) is a powerful tool for enforcing policies in Kubernetes and other cloud-native environments. By defining policies using a high-level declarative language and intercepting requests to the Kubernetes API server, OPA provides a flexible and extensible way to enforce security policies and other constraints on cluster resources. With OPA, you can ensure that your Kubernetes clusters are secure and compliant with your organization’s policies.

--

--

Sharon Sahadevan
Sharon Sahadevan

Written by Sharon Sahadevan

Founder @ kubenatives.com | I write about Kubernetes and Cloud Native echo system | https://www.linkedin.com/in/sharonsahadevan 🚀✍️

No responses yet