Kubernetes Policy - Open Policy Agent
Open Policy Agent(OPA) is a general purpose declaratively policy engine which can be used for applying policy across the cloud native stack. You can learn more here.
OPA Gatekeeper is a Kubernetes native policy tool used to enforce policies using the custom resource definition (CRD). It uses the admission controller in Kubernetes
- Validating Admission Webhook: This is used for validating or enforcing the policy
- Mutating Admission webhook: This is used to change or mutate the Kubernetes resource and currently is in alpha state
The policy evaluation is done using a language called Rego. More details of the language can be found here.
The gatekeeper can be installed using the plain YAML or using helm chart as mentioned here.
Once the gatekeeper is installed , We need to create a ConstraintTemplate resource using the Rego language. This will act as a template for defining various policy. It will also contain the schema for parameters which will be send to the template from the policy
apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8srequiredlabels spec: crd: spec: names: kind: K8sRequiredLabels validation: # Schema for the `parameters` field openAPIV3Schema: properties: labels: type: array items: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8srequiredlabels violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} required := {label | label := input.parameters.labels[_]} missing := required - provided count(missing) > 0 msg := sprintf("you must provide labels: %v", [missing]) }
The above policy template will check if the Kubernetes resource as the label defined which is sent as the parameter. We can the then define the policy using the kind defined in the ConstraintTemplate and specify the Kubernetes resource kind to which the policy should be applied along with the parameter value
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sRequiredLabels metadata: name: ns-must-have-gk spec: match: kinds: - apiGroups: [""] kinds: ["Namespace"] parameters: labels: ["gatekeeper"]
After creating the above policy, we will not be able to create a Kubernetes namespace without the label gatekeeper defined.
We can create a different policy using the same ConstraintTemplate template as shown.
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sRequiredLabels metadata: name: ns-must-have-lb-owner spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] parameters: labels: ["owner"] allowedRegex: "*.mycompany.com"
After creating the above policy, we will not be able to create a Kubernetes pod without having the label owner and the value that matches the Regex.
The community has created a library of the rego rules for most of the common policy in Kubernetes. More details can be found here.This library also contains the policy which can be used to define the pod security policy
We can also pass data to the policy evaluation by defining the config object and using that data for policy evaluation as defined in this example here.
It provides features like performing the audit of the resources which are not compliant within the cluster, Perform things like dry-run of policy before applying to the production cluster. It also provide lot of built-in metrics which can be send to tools like Prometheus to see the compliance details.
The latest addition to OPA is a tool called Conftest which also can be used with Gatekeeper. It is a command line utility based on Rego language which can be used to write test for the structured configuration data like Kubernetes configurations,Tekton pipeline definitions and Terraform code and can be used in your CI pipelines.