In the Kubernetes Admission Control tutorial we have seen how OPA can be deployed as an admission controller to enforce custom policies on Kubernetes objects. In that tutorial, policies were enforced on native Kubernetes objects such as ingresses.
This tutorial will show how OPA can be used to enforce polices on custom resources. A custom resource is an extension of the Kubernetes API that is not necessarily available on every Kubernetes cluster. More inforation on Kubernetes custom resources is available here.
The additional steps that need to be taken to achieve this are:
- Define a role for reading Kubernetes custom resources.
- Grant OPA/kube-mgmt permissions to read Kubernetes custom resources.
- Configure
kube-mgmtto load Kubernetes custom resources into OPA.
Same as the Kubernetes Admission Control tutorial.
minikube startFollow the steps in the Kubernetes Admission Control tutorial to create the opa namespace and configure TLS.
Save the following CustomResourceDefinition to resourcedefinition.yaml:
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: cats.opa.example.com
spec:
group: opa.example.com
version: "v1"
scope: Namespaced
names:
plural: cats
singular: cat
kind: Cat
shortNames:
- ctAnd create it:
kubectl create -f resourcedefinition.yamlUse the admission-controlller.yaml file from the Kubernetes Admission Control tutorial to deploy OPA as an admission controller with the following changes:
- Define a role for reading the Kubernetes custom resource created in the previous step.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: crd-reader
rules:
- apiGroups: ["opa.example.com"]
resources: ["cats"]
verbs: ["get", "list", "watch"]- Grant OPA/kube-mgmt permissions to the above role.
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: opa-crd-reader
roleRef:
kind: ClusterRole
name: crd-reader
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts:opa
apiGroup: rbac.authorization.k8s.io- Update the
kube-mgmtcontainer spec to load the Kubernetes custom resources into OPA.
name: kube-mgmt
args:
- "--replicate=opa.example.com/v1/cats" # replicate custom resourcesNow follow the Kubernetes Admission Control tutorial to deploy OPA on top of Kubernetes and register OPA as an admission controller.
Create a policy that rejects objects of kind Cat from sharing the same cat name.
name-conflicts.rego:
package kubernetes.admission
import data.kubernetes.cats
# Cat names must be unique.
deny[msg] {
input.request.kind.kind = "Cat"
input.request.operation = "CREATE"
name := input.request.object.spec.name
cat := cats[other_ns][other_cat]
cat.spec.name == name
msg = sprintf("duplicate cat name %q (conflicts with %v/%v)", [name, other_ns, other_cat])
}kubectl create configmap name-conflicts --from-file=name-conflicts.regoDefine two objects of kind Cat. The first one will be permitted and the second will be rejected.
cat.yaml:
apiVersion: "opa.example.com/v1"
kind: Cat
metadata:
name: my-new-cat-object
spec:
name: Whiskerscat-duplicate.yaml:
apiVersion: "opa.example.com/v1"
kind: Cat
metadata:
name: my-duplicate-cat-object
spec:
name: WhiskersFinally, try to create both Cat objects:
kubectl create -f cat.yaml
kubectl create -f cat-duplicate.yamlThe second object will be rejected since an object with the cat name Whiskers was created earlier.