By Gary Duan
Application owners and IT administrators have been looking for tools that can help them secure their application pipeline, from the development stage to deployment and production. How to do this reliably and efficiently without slowing down development processes remains a big challenge. This is where Open Policy Agent (OPA) and Kubernetes Custom Resource Definitions (CRD) can help.
The concept of infrastructure-as-code has become popular in recent years. The essence of this process is not only to describe the infrastructure in text format, but also to express the desired states in declarative languages. The declarative nature decouples system definitions from the actual implementations. Using these tools, the DevOps team is able to manage the complexity of the infrastructure at scale.
Similarly, this concept can be adapted to automate security policy operations as well. Companies have to enforce security policies in order to meet legal and compliance requirements. With more and more software components being used across different deployments and geolocation, using manual processes to impose policies is error-prone, unmanageable, and unscalable.
OPA is a general-purpose policy engine. Policies are written in a declarative language called Rego that offers rich constructs to translate human-readable rules into unambiguous programs. The typical workflow is,
- The application sends the policy request to the OPA engine;
- The OPA engine then evaluates whether the request conforms to the defined policy;
- The application enforces the policy decision after the evaluation result is received.
Because of its declarative nature, OPA is a powerful tool that helps automate policy decision-making and enforcement of workflows in modern applications. As a general-purpose engine, OPA can be integrated into many applications. The most prominent examples include the gatekeeper project, which integrates with the Kubernetes Admission Control function; and Styra’s DAS project that provides authorization policy for microservices.
Following is an example of how to utilize OPA for policy decision-making and auditing in different stages of the application lifecycle.
Integrate OPA in CI/CD pipeline scanning
Several vendors, including NeuVector, offer various scanning plugins for CI/CD tools, such as Jenkins or Azure DevOps Services. The typical workflow is, after the CI/CD pipeline process creates the image, the scanning plugin is invoked to inspect the vulnerabilities in the image; if the scanning result doesn’t pass the defined checks, the image build pipeline stops and the developer is notified to fix the vulnerabilities. The whole process is automated.
These scanning plugins usually provide basic configurations that allow users to define the pass criteria, such as the maximum number of the high severity vulnerabilities allowed in the images, but fall short when the rules become more complex. For example, consider the following rule:
|Number of high severity vulnerabilities that have been reported for more than 30 days must be less than 5.|
Most pipeline scan plugins don’t offer this level of sophistication. This is where OPA shines. If you know the scan result format of NeuVector’s RESTful API, the above policy can be codified in the following Rego language.
Using NeuVector RESTful API, you can easily write a shell script to scan the specified image and invoke OPA to evaluate if the above policy is satisfied.
If the script’s output is “false”, the policy evaluation fails and the build pipeline should stop.
The above example demonstrates that OPA’s REGO language is able to precisely express complex policy rules. Because OPA engine’s footprint is small and it offers RESTful API and golang interfaces, it can be easily integrated into your CI/CD pipeline.
Audit NeuVector CRD Run-time Policy with OPA
A vulnerability scan provides a snapshot of the container image’s security state at the time the image is scanned. After the image is deployed into the production environment, new vulnerabilities can be discovered. In the real world, most applications have to run with vulnerabilities, known and unknown, in production. It is critical to protect your container application at run-time.
In order to put security-as-code concepts into practice in the production environment, help from a Kubernetes native construct is needed. Kubernetes is a declarative system, while system and application configurations are defined in a set of YAML files. Kubernetes enables vendors to extend its APIs with Customer Resource Definitions, or CRD. NeuVector allows our users to define an advanced container run-time security policy in CRD. Once they are applied, the policies are consumed by the NeuVector installation in the cluster.
Here are some highlights of NeuVector’s CRD policy.
- Define application’s network, process and file system behaviors in the YAML file;
- Network segmentation rules at the layer-7 protocol level;
- Cluster ingress and egress access control with external resources’ DNS names;
- Support RBAC and multi-team use cases;
- Support both monitor mode and protect mode;
- Ease migration from staging to production.
How do you ensure that rules defined in CRD meet company-wide policies? Luckily the CRD yaml files can be easily consumed by the OPA engine. We can use OPA to ensure the CRD rules are correct and complete.
For example, given the following run-time security policies:
The REGO file that codifies this policy and example input CRD file can be accessed on my github here.
These two examples demonstrate how to use OPA to make policy decisions and audit Kubernetes CRD rules. As OPA is a general-purpose policy engine, it has many other applications in various stages of the entire container lifecycle. It is a powerful tool that enables and encourages application owners and IT administrators to write reliable and auditable policies in order to secure their cloud-native applications.
For an on-demand demo recording, please see my recent OPA demo hosted by the CNCF.