Development

Policy as code for Kubernetes with Terraform

As you scale microservices adoption in your organization, the chances are high that you are managing multiple clusters, different environments, teams, providers, and different applications, each with its own set of requirements. 

As complexity increases, the question is: How do you scale policies without scaling complexity and the risk of your applications getting exposed?

What is Policy as Code?

As your infrastructure grows, your teams, applications, and policy management rarely scale well together, mainly because you will need to enforce different policy levels for each team and application you onboard. 

Policy as code can help you address this by enabling you to codify your different policies and automatically enforce them. By declaring policies as code, you can implement practices such as version control and automated policy deployment.

Policy as code also enables operations and security teams to audit policies implemented, past policy changes, and report on how applications comply with them.

This approach drastically reduces human error and increases efficiency when creating, managing, and auditing application policies.

Challenges with Policy as Code

Policy as code presents clear benefits, and you should implement it as early in your pipeline as possible. While this statement is obvious, you may come across the following challenges when implementing and scaling it:

Lack of central management:

The lack of a cohesive and centralized system to track which policies exist and which rules they contain can be problematic. Suppose you have applications deployed across different clusters by different teams where each cluster requires a different set of enforced policies. In that case, it can become challenging for you to manage the rules efficiently and report to your security teams on what rules are in effect and how applications are complying with them.

Not application-focused:

Most tools currently focus on the underlying infrastructure, such as Kubernetes, rather than the application itself.

Focusing on the infrastructure can impose risks and increase complexity. You will need to use different mechanisms for setting policies for applications deployed on Linux vs. ones deployed on Kubernetes.

Additionally, tying your policy as code approach to the underlying Kubernetes cluster can create complexity as you scale across different clusters, versions, providers, and application requirements. A cluster-based approach can make you dependent on developers’ ability to fully understand the business and application requirements and code them accordingly, making it complex for security teams to audit them properly.

Complex policy change-tracking:

Policies are rarely set-them and forget-them, and they are regularly updated as users come and go, applications evolve, and so on. If your policy as code approach does not allow you to easily use Git as the tracking mechanism, it can become complex to audit policies, roll back changes, and more.

Policies as Code with Terraform

Terraform is one of the IaC (Infrastructure as Code) platforms supported by Shipa. When combining Terraform and Shipa, you can achieve a simple and easy-to-implement application policy engine.

The combination enables you to define, enforce, and manage policies, or policy frameworks as they are called in Shipa, using a simple definition that does not require formal knowledge of programming, learn a new language, or the underlying complexities of Kubernetes.

By using the approach above to defining policy as code, you:

  • Detach the application-level policy from the underlying infrastructure, enabling teams to define policies focusing on the application without having to write complex rules in different programming languages or learning Kubernetes in detail to be able to do so.
  • Have a central management platform to manage and report on policies currently available.
  • Can easily manage policy definitions from Git.

As a bonus, you also remove the need for developers to have access to kubectl 🙂 

Let’s see how Terraform and Shipa can help you get started with a policy as code approach:

Registry control:

Using the code snippet below, you can use Terraform to create a policy framework in Shipa and limit the container registries that developers can use when deploying applications bound to this policy framework:

terraform {
  required_providers {
    shipa = {
      version = "0.0.3"
      source = "shipa-corp/shipa"
    }
  }
}

provider "shipa" {
  host = "htt://target.shipa.cloud:8080"
  token = "<your-shipa-token>"
}

resource "shipa_framework" "dev-framework" {
  framework {
    name = "cinema-services"
    resources {
      general {
       container_policy {
          allowed_hosts = ["docker.io/shipasoftware", "docker.io/shiparepo"]
        }
      }
   }
  }
}

Network Policies:

Let’s say you want all applications deployed using this policy framework to have a certain network policy attached to it by default as they are deployed. You can use the example below for that:

terraform {
  required_providers {
    shipa = {
      version = "0.0.3"
      source = "shipa-corp/shipa"
    }
  }
}

provider "shipa" {
  host = "htt://target.shipa.cloud:8080"
  token = "<your-shipa-token>"
}

resource "shipa_framework" "dev-framework" {
  framework {
    name = "cinema-services"
    resources {
      general {
       network_policy {
          ingress {
             policy_mode = "allow-custom-rules-only"
             custom_rules {
              id = "rule-name"
              enabled = true
              description = "rule description"
              allowed_apps = ["app1", "app2"]
              ports {
                port = 8080
                protocol = "TCP"
              }
             }
          }
          egress {
             policy_mode = "allow-all"
          }
          disable_app_policies = "false"
        }
   }
  }
}

Notice that the definition above is easy to implement and does not require you to manage Istio policies directly. Defining those using Shipa and Terraform also ensures that rules are validated before applied and gives you a network dependency map for the applications deployed:

Security Scanning:

You can also use Shipa’s policy framework and Terraform to define the level of security scanning you want for images deployed through a specific policy framework and any vulnerabilities you want to treat as exceptions, if any. Here is an example:

terraform {
  required_providers {
    shipa = {
      version = "0.0.3"
      source = "shipa-corp/shipa"
    }
  }
}

provider "shipa" {
  host = "htt://target.shipa.cloud:8080"
  token = "<your-shipa-token>"
}

resource "shipa_framework" "dev-framework" {
  framework {
    name = "cinema-services"
    resources {
      general {
       security {
          disable_scan = false
          ignore_components = ["apt", "bash", "..."]
          ignore_cves = ["CVE-2020-27350", "CVE-2011-3374", "..."]
        }
     }
    }
  }
}

Just like the network policy rules applied, you can also see reports of your application’s security scan result directly on Shipa’s dashboard:

Policy Changes:

You and your DevSecOps team can also have clear visibility over changes in the policy framework, making it easy for teams to audit policies currently being enforced on applications and how they changed over time.

Centralized Management:

Find centralized policy information easily and how they affect your clusters and applications once applied by Terraform using Shipa’s dashboard.

Conclusion

You can find further details on using Terraform and Shipa to define your policies and additional policy controls you can implement here: Framework Management (shipa.io)

Implementing an application-focused policy as code approach gives you clear benefits, enables you to scale infrastructure quickly without compromising security, and brings clear visibility and control over the policies enforced across your different clusters, environments, and applications.

Planning a structured policy as code model from the beginning that can be controlled and versioned easily will enable you to bring together DevOps and DevSecOps under a standard policy definition and management layer.