Illustration: Open Policy Agent
Enforcing Kubernetes a policy with Open Policy Agent
This article’s goal is as follows,
- Run Open Policy Agent on top of Kubernetes
- Create a minimum policy for Open Policy Agent which is similar to tutorial
- Check that the policy is enforced to requests in Kubernetes
What is Open Policy Agent (OPA)
Open Policy Agent (OPA) is a policy engine which enforces Kubernetes and its requests to obey given policies. Its main benefit is that Kubernetes administrator can secure her/his organization with rejecting any requests that might break rules.
OPA executes two kinds of policy check.
- Validation : Admit requests which follow rules and reject other requests
- Mutation: Update request contents in order to follow rules
We can apply OPA policy to Docker, Kubernetes, SSH, Terraform and Envoy.
At this time, OPA v0.17.1 is available.
OPA can read REGO language in policy files.
I will show the installation process and check results of OPA.
Prepare OPA environmet
First, I prepared this environment
- Kubernetes (using Kind)
- kubectl, helm
There are two packages which enables Kubernetes to support OPA control.
- kube-mgmt
- Gatekeeper
I tried kube-mgmt this time because I am using helm
and kube-mgmt supports Mutating
Helm package for kube-mgmt and OPA is published here.
(1) Install OPA (with kube-mgmt) onto Kubernetes
I created a Namespace called opa
.
kubectl create namespace opa
Next, I created a configuration file for helm
installation.
# admissionControllerKind: I chose Mutating
admissionControllerKind: MutatingWebhookConfiguration
# opa: No need to include existing policy files
opa: null
# mgmt: We have to enable this feature in order to add configmap
mgmt:
configmapPolicies:
enabled: true
namespaces: [opa, opa-example]
requireLabel: true
replicate:
cluster:
- v1/namespaces
namespace:
- extensions/v1beta1/ingresses
# rbac: OPA needs to access these kinds of resources in Kubernetes
rbac:
create: true
rules:
cluster:
- apiGroups:
- "*"
resources:
- configmaps
verbs:
- get
- list
- watch
- patch
- update
- apiGroups:
- "*"
resources:
- namespaces
- ingresses
verbs:
- get
- list
- watch
sar:
enabled: true
authz:
enabled: false
I installed OPA and kube-mgmt with helm and this configuration file (doc).
$ helm repo add open-policy-agent https://open-policy-agent.github.io/kube-mgmt/charts
$ helm repo up
$ helm install opa open-policy-agent/opa -f helm-values.yaml --namespace opa
(2) Create a Policy
The system overview is like this.
This OPA example checks Ingress addition requests..
Kubernetes configuration is as follows.
- All requests is about creation of ingress
data
is information in Kubernetes itself (Namespace
configuration)policy
includes two policy files; the first is a default policymain.rego
, and the second is a policyingress-whitelist.rego
that is specific forIngress
resource.
Take a close look at these policies.
The first is main.rego
. This allows all requests basically.
The second is ingress-whitelist.rego
. This allows some Ingress
addition requests whose hostname is supported in Namespace
and rejects other requests.
I added ConfigMap
resource including these two files. This example command finishes two files with one command. But it is not necessary and you can use seperate ConfigMap
resources for each file.
The most important point is that it must include a specific labal openpolicyagent.org/policy=rego
that enables OPA to include the ConfigMap
as policy.
$ kubectl create -n opa configmap policy --from-file ./main.rego --from-file ./ingress-whitelist.rego
$ kubectl label -n opa configmap policy openpolicyagent.org/policy=rego
I checked the policy was imported into OPA.
After OPA imported this ConfigMap
as policy, special annotation openpolicyagent.org/policy-status: ‘{“status”:”ok”}'
was added in the ConfigMap
automatically by OPA. I confirmed the policy was successfully imported.
(3) Check the Policy working
Last, I checked if the policy was working like this.
I created a Namespace
for testing.
This Namespace
has an annotation ingress-whitelist
which can be seen from OPA. This Namespace
is found to allow two patterns of hostname in Ingress
; *.ok.com
and *.secondok.com
.
$ kubectl apply -f test/namespace.yaml
namespace/opa-example created
I tried to create these Ingress
resources in this Namespace
.
- ingress-ok.yaml
2. ingress-ok2.yaml
3. ingress-bad.yaml
These Ingress
resource configurations are different in only hostname.
- host: test.ok.com
- host: test2.secondok.com
- host: test.ng.com
I checked if these Ingress
configurations could be added in Kubernetes.
$ kubectl create -f test/ingress-ok.yaml
ingress.extensions/ingress-ok created
$ kubectl create -f test/ingress-ok2.yaml
ingress.extensions/ingress-ok-2 created
$ kubectl create -f test/ingress-bad.yaml
Error from server (invalid ingress host "test.ng.com"): error when creating "test/ingress-bad.yaml": admission webhook "webhook.openpolicyagent.org" denied the request: invalid ingress host "test.ng.com"
Here is what I got.
The first two Ingress
configurations were successfully added to Kubernetes. But the last one could not be added with displaying some error. This was meant to be. The last one included unsupported hostname by Namespace
(not included in *.ok.com
and *.secondok.com
). And I found the error message was created by ingress-whitelist.rego
policy as the form of msg
.
I confirmed the OPA policy was working correctly.
Summary
I confirmed basic function of OPA with simple environment.
- Ran OPA on top of Kubernetes
- Added simple policies as
ConfigMap
- Checked the policies were working successfully after I added some
Ingress
resources
I found OPA was powerful. This would be possibly universal policy engine across Kubenetes and other platform tools.
Writing a policy in the REGO language, which is a special programming language, is a great feature, and at the same time, I feels like it raises the barrier to entry a little.