As Kubernetes adoption increases, policies have become a critical foundation to operate, control, and secure Kubernetes clusters. Rather than making assumptions about how workflows operate, organizations have defined different policies to meet security compliance requirements and achieve generalization across multiple systems.
While Kubernetes provides various capabilities through Role-Based Access Control (RBAC) to govern and control aspects of clusters, it lacks the ability to enforce finer-grained policies. To achieve granular policy enforcement, cluster admins must use automated ways of defining policies through policy engines like Open Policy Agent (OPA).
Projects like Open Policy Agent (OPA) leverages the Kubernetes admission controller’s extensible design and control the configurations of specific resources to support Kubernetes RBAC while serving as the foundation to comply with regulatory compliance such as PCI and HIPAA.
To properly implement OPA, it is important to understand its working; that’s why in this blog, we will have a deeper look at OPA, its components, features, and how it complements Kubernetes for cluster operations and policy requirements.
Open Policy Agent(OPA) is an open-source policy integration toolkit aimed towards unified policy enforcement for various technologies like Kubernetes, microservices, and CI/CD pipelines.
Styra developed OPA in 2016 as a general-purpose policy engine. It has become a part of CNCF as an incubating project and used by tech giants like Netflix, Cloudflare, Pinterest to enforce policies on their Kubernetes clusters.
OPA addresses Kubernetes’ authorization challenges by providing IAM capabilities, controlling access to internal resources, and integrating with APIs, the Linux SSH daemon, or an object-store. OPA is incredibly versatile and can easily handle any valid JSON data as request attributes. The decisions are not based on a specific format and are agnostic to API and schemas.
OPA supports the practice of policy and security as code by evaluating inputs against user-defined policies using REST API. OPA checks if the policies met the required criteria or not and returns a decision to the actual service, which further processes the enforcement.
OPA only handles the policy decision and checks whether a request conforms to the required policies. This is how it becomes a domain agnostic policy tool that supports many services or applications.
Any application or service that determines policy decisions using API configuration can seamlessly integrate with OPA. Kubernetes API integrates with OPA for cluster configuration management and security compliance to test resource schemas fields and determine cluster resource types.
Overall, the primary purpose of OPA is to provide a generalized engine that allows devs and operations to have more granular control over service provisioning and interaction during runtime.
OPA implements a high-level declarative language – Rego to define policies and address authorization requests. Rego includes a set of functions and operators, which provides lots of flexibility for policy evaluation.
OPA uses policies written in Rego for evaluating resource requests made to the Kubernetes API server. The requests are denied even if a single policy fails and only allowed when all the policies met the decision criteria.
OPA deployment can be done in various ways depending upon the specific situation. OPA can be implemented as a Go library if the application is written in Golang. Applications not using Go can deploy OPA as a daemon using a sidecar container for increased performance and reduced latency.
OPA provides a central authorization system for infrastructure comprising multiple technologies and services written in different languages. OPA implements policy-as-code throughout the stack so systems running Kubernetes at the core can easily roll out new policies and changes.
OPA utilizes a fully-featured set of APIs for sending, determining, and logging policy data.
A Bundle service API is utilized to search new policy versions and send policy data to OPA, while a Status service API determines the current policy status on OPA.
Also, OPA uses a decision log service API to log every policy decision and send those to the log service API for audit and troubleshooting purposes.
As mentioned above, admins can integrate OPA with Kubernetes API to provide various resource management benefits. For instance, OPA can ensure no images are pulled from the malicious directories, and the container only uses docker-certified images. OPA can also deny access to ingress hostnames and request/limits in a cluster for unauthorized namespaces.
OPA can integrate well with many modern-day systems and platforms other than Kubernetes like Kafka, SQLite, CEPH, and Terraform. It also integrates with Linux using the PAM plugin to enforce advanced policy controls.
OPA provides the ability to mantain all the policies from a source control repository like Git. This makes modifying existing policies or introducing new ones relatively easy as APIs will dynamically manage the loaded policies and reduce the operational overhead to manage every system manually.
OPA can be used to complement RBAC and Pod security policies(PSPs) to have granular control over the Kubernetes cluster. Users controlling pod fields in resource types using OPA do not have to write custom admission controllers for each specific use case. OPA, by default, supports multiple configurations for different resource types, which can provide more reusability.
Gatekeeper is a project under the OPA landscape that integrates Kubernetes and OPA through an admission controller on top of the policy engine. Gatekeeper aims to provide a Kubernetes native way for policy enforcement and is installed as a ValidatingAdmission Controller Webhook in a Kubernetes cluster.
Gatekeeper uses Rego policies for determining non-root users, specific resource labels, and ensuring pods resource requests and limits. OPA Gatekeeper intercepts the Kubernetes API requests as a mutating admission controller and modifies the incoming request for PSPs.
Gatekeeper validates by checking whether the request meets the defined policy or not; it does that by creating a custom resource definition (CRD) which allows the creation of constraint templates for enforced policies. Constraint templates contain the code logic and policy schema, simplifying more constraint instances for specific resources.
For example, let’s take a policy that we want to enforce to prevent teams from creating a service of type x in the particular namespace of the cluster. We can create a ConstraintTemplate that can be used to check if the resource object for a service type is contained in the validation request.
That ConstraintTemplate object doesn’t validate on its own. It creates a custom resource in the cluster and enforces the policy by creating a constraint of that new resource type. Once the policies are enforced, all pods in the particular namespace are denied access to that particular service.
Also, to prevent teams from creating another type of service, Gatekeeper can parameterize the template to support configuration for different service types.
While OPA Gatekeeper provides incredibly powerful capabilities for Kubernetes and other platforms, it has its limitations. As of now, the OPA admission controller is deployable on a singleton pod pattern which means there is only one instance of OPA running at any given time.
There are many scenarios where organizations want to ensure high availability for a specific number of pods; support for that is planned for future releases.
Also, OPA Gatekeeper through Rego introduces adoption issues. Although there is an extensive library of policy examples, and it is easy to get started, Rego is not a trivial language to implemented complex policies. Rego’s alternatives are available like Kyverno, which also offers good functionality for Kubernetes native policy management.
Gatekeeper is more established in the community and supports multiple replicas for availability and scale compared to the young establishment of Kyverno. Gatekeeper does not have any policy generation capabilities and is mainly used for validation use cases, while Kyverno provides policy generation and syncing ability to handle more use scenarios and provide a high degree of flexibility.
OPA can effectively implement security policies and allow admins to implement fine-grained controls to improve the overall security of Kubernetes clusters. OPA policies are checked and validated against hundreds of security constraints providing the user with information on which objects are not in compliance with the defined criteria.
Moreover, OPA Gatekeeper implements different usage scenarios not covered by Kubernetes RBAC and PSPs. Cluster admins can run, operate, and model security policies in a single OPA admission controller to unify policy management and enable Engineering, DevOps to easily collaborate and mitigate issues.
Gatekeeper also can apply policies early in the CD pipeline through cluster APIs while implementing them in production or testing environments.