No More Manual Reviews — Policy as Code to the Rescue
Using policy as code is the most advanced method of implementing policy-based governance. In this post, we look at how policies are used to automate the entire workflow of security & compliance.
GitOps Cloud Security Model - An Infographic
MITRE ATT&CK Matrix for Kubernetes
What is Policy-as-Code and Why it's Needed?
Automation was the original benefit of DevOps, but GitOps is what enables automation without the downside of poor security, and things breaking in production. As infrastructure, networking and more start getting defined as code, all its inherent artifacts like configuration management, provisioning manifests, runbooks, deployment scripts, and packages become testable as code. The opportunity here is to leverage this to automate manual reviews and processes that need not be done by developers or operations folks. Policy as code makes this possible.
Kubernetes configuration is generally defined in YAML which is used to describe the constraints and relationships between various Kubernetes resources. While YAML’s format is quite readable, it’s not practical to use it to produce valid configurations at scale. Static validation alone is not sufficient to catch errors in YAML configurations and may leave various security issues exposed. Using policy as code can enforce security and compliance in the development pipeline and help make systems more resilient.
What is policy as code?
As the name suggests, policy as code (PaC) is the codification of an organization’s policies that allows them to manage their IT operations by defining rules declaratively. High-level programming languages like Python, YAML, and Rego are commonly used to define such policies, but the final choice depends on the enforcement tools and policy engine being used. A policy engine would take a query input and expresses the generated policies in a declarative manner.
The benefits of using policy as code are conceptually similar to that of infrastructure as code (IaC) which essentially codifies an organization’s infrastructure setup. However, the drawback of traditional IaC is that it relies heavily on manual reviews at every step. This is counterproductive. Instead, PaC goes the distance by implementing built-in checks automatically conducted by software tools and agents rather than humans. These agents rely on pre-defined policies to tell good configurations from bad ones. This approach has a high degree of confidence as tools are better and more consistent at enforcing policies than humans. As a result, you get benefits like greater developer velocity, higher deployment frequency, and reduced friction between development and SecOps teams.
PaC empowers software delivery teams to enforce specific standards within certain clusters or across the organization while simultaneously reducing variations in their infrastructure and the attack surface and maintenance costs. Moreover, deploying policy as code also automates numerous redundant tasks and helps scale efficiency at an organizational level.
How Policy as Code automates configuration management at scale
All code-centric processes like building, testing, and configuration management are prone to security threats and PaC can help automate the age-old manual process of ensuring product security and compliance. It does so by automating all pipeline security and compliance checks, thus preventing the developer from bypassing critical security protocols.
For example, a server is subscribed to policies based on the group definition, and all these policies are run against the server. For every software product released to production, certain checks are made to ensure that it conforms to the security standards followed by the organization. For instance, the National Institute of Standards and Technology’s (NIST) 800 standards are widely recognized security standards that can be translated to code given the context. Doing this ensures that configuration settings remain consistent across all deployments, especially when these policies are to be executed every few minutes based on the organization’s aversion or tolerance to risk.
Policy as code in GitOps Pipeline
Policies can be applied at every step of the software lifecycle - from infrastructure provisioning to runtime security. Let’s look at each phase, and the role that policies play in automating and securing the steps involved.
Infrastructure as code scanning in Git
At this stage, the developer receives commit-time feedback. When policy is enforced by the policy engine it scans the infrastructure as code templates before they are committed to the Git repository while also attempting to auto-remediate violations wherever possible.
Terraform is a well-known open-source declarative IaC framework and is used to define resources in the public cloud. It is composed of more than three thousand modules, many of which are misconfigured (some studies peg the number of failed checks at 50%). This makes scanning at this stage and validating all the templates before committing them to the Git repository all the more crucial.
Security guardrails in the CI system
At this stage, the development team receives build-time feedback where the build fails if any policy violations are detected in the newly generated manifests. These can be for any violations, such as exposing secrets in code or failed authentication at any of the steps.
Deployment-time feedback from Kubernetes clusters
If the deployment artifact violates any policies, the policy agent is responsible for preventing both manual and automatic deployments from being introduced to the Kubernetes clusters. The development team also receives deployment-time feedback explaining why the deployment was stopped. If this doesn’t happen, various potential security risks such as over-privileged containers, insecure networking configurations, and insecure RBAC policies, can arise when an application is deployed into production.
Run-time security and compliance
While GitOps has pre-established guardrails in place to prevent unauthorized modifications, the continuous reconciliation of the desired state ensures that the application version stored in Git and the one running in Kubernetes clusters are the same. If not, changes are automatically reverted. Though this may seem necessary for root cause analysis, it works wonderfully well to ensure that cloud-native systems stay secure over time.
Implementing policy as code with Weave GitOps
Weave GitOps is a continuous operations product that facilitates the deployment and overall management of Kubernetes clusters and applications regardless of the environment or scale. With recent developments, we can now implement policy as code in GitOps pipelines and use it to automate DevSecOps. Using policy as code essentially guarantees the necessary security, resilience, and compliance with established coding standards across all applications and infrastructure in an organization.
Weave GitOps has an in-built policy library that features more than 100 policy examples covering HIPAA, SOC2, GDPR, Mitre Attack, PCI-DSS, among others, and all these policies are built on OPA (Open Policy Agent), which is significantly easier to manage with GitOps. The GitOps policy as code engine ensures that the system remains protected from code commit to deployment to runtime - this is what we call Trusted Delivery. Let’s look at what this means for different parts of the pipeline.
The Trusted Delivery solution - running policy as code using Weave GitOps - introduces the ability to develop one policy and apply it across the software development cycle - with subtle variations by team or product, or project if needed. Weave GitOps allows each leaf cluster to run its policy engine, which ensures continuous policy evaluation even during network disruptions. The policy as code checks in this environment provides automatic detection of misconfigurations and ensures continuous policy evaluation should any disruptions occur. Moving from manual to automated code and security reviews used to be a nice-to-have, but today, with solutions like Weave GitOps, it is a reality.