IaC Security and Compliance with Regula
Infrastructure as Code (IaC) is an essential piece of the modern software development landscape. IaC tools allow teams to define their infrastructure in a reproducible-automated fashion, increasing speed and consistency while preventing errors, misconfiguration, and configuration drifts.
IaC also plays an important role in security. It gives visibility over the whole infrastructure, including its security aspects and components, even before they have been deployed. Development and/or security and operations teams can define sensible security defaults and a security baseline enforcing best practices that are automated and applied via the CICD pipeline, where changes can be reviewed and approved following the separation of duties principle.
Following this idea of anticipating security checks in the CICD pipeline, we can then define policies that automatically run against our infrastructure code and check for compliance rules as a step of the pipeline. In this tutorial, we will review the Regula policy engine, a tool that evaluates infrastructure as code files for potential Cloud security and compliance violations.
Regula includes a list of pre-defined rules for AWS, Azure, Google Cloud, and Kubernetes based on their respective CIS benchmarks. Regula also allows you to define custom rules written in Rego, OPA’s native query language.
Download Regula
Here we are going to download and get Regula ready for use following the most straightforward approach. Follow the installation guide for a complete list of methods for different platforms.
version=1.6.0
platform=macOS_x86_64
curl -L https://github.com/fugue/regula/releases/download/v1.6.0/regula_${version}_${platform}.tar.gz -o regula.tar.gz ; tar xzvf $_
Change the version
and platform
accordingly to your needs.
Check it.
./regula version
v1.6.0, build e2ae463, built with OPA v0.28.0
Verify Terraform Security and Compliance Violations
For this tutorial, we are going to use code examples from the microservices-demo repository. Let’s start downloading some Terraform configuration.
mkdir terraform
demo_base_folder=https://raw.githubusercontent.com/microservices-demo/microservices-demo/master/deploy/kubernetes
for f in main.tf variables.tf outputs.tf; do
curl -L $demo_base_folder/terraform/$f -o ./terraform/$f
done
Use your own infrastructure as code
Feel free to use your infrastructure as code to perform these tests.
Now let’s run Regula. For the simplest version of the regula run
command, we have to provide the root location of the configuration files.
./regula run ./terraform
# ommiting results
FG_R00377: VPC security group rules should not permit ingress from '0.0.0.0/0' except to ports 80 and 443 [Medium]
[1]: aws_security_group.k8s-security-group
in terraform/main.tf:5:1
Found 10 problems.
The output of the run command is human-friendly, listing all the non-compliant rules along with their descriptions, location, and severity.
Also, note that the command returns
a non-zero exit code echo $?
given the minimum severity set as default (unknown
, the lowest severity used for rules without a severity specified).
You can change the minimum severity to return a non-zero exit code using the -s, --severity
flag.
./regula run --severity critical terraform
# ommiting results
echo $?
0
The possible values are informational
, low
, medium
, high
, critical
and off
(never exit with a non-zero exit code).
Being able to check the output is useful. Still, we often want to send this result to a place where we can better visualize this data and/or monitor compliance rules across different code repositories. For this, you can use the -f, --format
to output the result as json and send it to your preferred place for consumption.
./regula run --format json terraform
Optional: Send the results to SQS
You need to have AWS credentials with the proper permissions configured in your local environment to follow this step.
Create an SQS Queue.
iac_compliance_queue=iac_compliance
iac_compliance_queue_url=$(aws sqs create-queue --queue-name $iac_compliance_queue --query QueueUrl --output text)
Send the results to SQS.
./regula run --format json terraform | aws sqs send-message --queue-url $iac_compliance_queue_url --message-body file:///dev/stdin
From here, you can consume this message and send this data for aggregation, monitoring or alerting in other tools.
Check and clean up.
# if you want to check the message created
aws sqs receive-message --queue-url $iac_compliance_queue_url | jq -r '.Messages[] | .Body'
# remove the queue to clean up
aws sqs delete-queue --queue-url $iac_compliance_queue_url
In time, note that the maximum message size in SQS is 256 KB. If you have a large codebase to be scanned, you need a different approach, such as sending the results to S3 and a notification to SQS.
Kubernetes Security and Compliance Violations
As per the date of this writing, a recent feature added to Regula is the support for Kubernetes.
Let’s see how it works.
Download an example from the microservices-demo repo as we did for Terraform.
mkdir k8s
curl -L $demo_base_folder/complete-demo.yaml -o ./k8s/complete-demo.yaml
Run Regula.
./regula run -t k8s ./k8s
# ommiting results
FG_R00496: Pods and containers should apply a security context [Medium]
[1]: Deployment.sock-shop.catalogue-db
in k8s/complete-demo.yaml:205:1
[2]: Deployment.sock-shop.queue-master
in k8s/complete-demo.yaml:516:1
[3]: Deployment.sock-shop.rabbitmq
in k8s/complete-demo.yaml:568:1
Found 55 problems.
This time we are providing the -t, --input-type
flag for Kubernetes.
Kubernetes Custom Policy
One of the main Regula features, in my opinion, is the ability to write your policies using Rego.
Let’s create a custom Rego policy to check whether a Kubernetes Pod has set the containers’ resources requests and limits for cpu and memory.
mkdir k8s/custom
cat << EOF > k8s/custom/containers_resources.rego
package rules.k8s_containers_resources
import data.fugue
import data.k8s
__rego__metadoc__ := {
"id": "CUSTOM_R00001",
"title": "Pods should specify containers compute resources (cpu and memory) requests and limits",
"description": "Pods should specify containers compute resources (cpu and memory) requests and limits. Specifying containers resources requests and limits is considered a best practice.",
"custom": {
"severity": "Low"
}
}
input_type = "k8s"
resource_type = "MULTIPLE"
container_resources_set(template) {
container = template.spec.containers[_]
container.resources.limits.cpu != null
container.resources.limits.memory != null
container.resources.requests.cpu != null
container.resources.requests.memory != null
}
policy[p] {
obj := k8s.resources_with_pod_templates[_]
count(obj.pod_template.spec.containers) > 0
container_resources_set(obj.pod_template)
p := fugue.allow_resource(obj.resource)
}
policy[p] {
obj := k8s.resources_with_pod_templates[_]
count(obj.pod_template.spec.containers) > 0
not container_resources_set(obj.pod_template)
p := fugue.deny_resource(obj.resource)
}
EOF
Now we can check the custom policy.
./regula run -t k8s --include ./k8s/custom --user-only ./k8s/complete-demo.yaml
CUSTOM_R00001: Pods should specify containers compute resources (cpu and memory) requests and limits [Low]
# ommiting results
Found 6 problems.
In this command, we include the custom policy with -i, --include
and disable the default rules with -u, --user-only
to make it easier to visualize the output of our custom rule.
Check the Open Policy Agent documentation to learn more about Rego and the Regula documentation to learn more about how to write custom rules.