In this demonstration, I’ve configured OPA policy at the K8s cluster, allowing only the Spinnaker service account to create a deployment via the kube-api server. Additionally, I’ve defined a policy within the pipeline via the Armory Policy Engine, requiring all images be specified with a tag other than ‘latest’. This demonstrates centralization and consolidation of admission policy for K8s.
Safe Continuous Deployment/Delivery is a key focus for Armory. Establishing policy-driven governance as a first-class citizen in CD pipelines is one way Armory enhances this goal. Through policy, elements of a CD pipeline are controlled at a much finer grain than RBAC alone.
Open Policy Agent (a.k.a. OPA) is a project well known to Kubernetes administrators, providing policy governance for K8s where K8s RBAC leaves off . It is self-described as, “An open source, general-purpose policy engine that enables unified, context-aware policy enforcement across the entire stack”. So, OPA is is a general purpose policy engine that can integrate with any stack, K8s being one of them.
Armory Policy Engine integrates OPA with the CD stack. Policy is applied consistently before deployment, enabling the CD platform to consider policy specific to pipeline creation and execution, along with admissions policy a kube-api server might otherwise rely on OPA for.
With OPA we define allow/deny rules that can be applied to requests (e.g. CRUD operations, conditional approvals, etc.). These rules are evaluated within the context of a request. When used with K8s, we insert OPA as an Admission Controller. The kube-api server checks with OPA before executing any CRUD requests that have passed RBAC privilege check.
For example, a principal might have RBAC privileges to create a pod, but we need to ensure the request only pulls images from a trusted registry. With OPA we would define the list of allowed registries, the kube-api server would check the request against RBAC and then pass it to OPA, OPA would parse the registry/image value and return an allow/deny based on the defined policy.
One model I’ve recently begun contemplating is applying policy at the K8s cluster level to effectively deny all requests unless they originate from a CD pipeline. From the pipeline, we would manage the K8s admission policy.
This can be applied across all target clusters, preventing any direct interaction with resources via the kube-api server, while enforcing consistent policy from a single policy set definition. Essentially a single (non-replicated) policy for potentially thousands of K8s clusters that is immediately consistent. Using CD and K8s RBAC, we can restrict privileges to only update the OPA rules via the same CD platform pattern. The end result is an entirely auditable and secure single-source for all K8s cluster policy.