Custom Checkov Scans
Introduction
This article is a continuation of my previous post. In this article, we will be exploring the use of custom Checkov checks for specific checks against our AWS resources that are not covered by the default checks.
Suppose we have an organisation requirement that requires our Lambda function to have a maximum of 2GB of memory to save on cost. By default, there are no Checkov policies that can help to enforce this. This is where custom policies become helpful.
Let’s deploy a Lambda function using Terraform. This is what the Terraform would look like. Take note that we are setting the memory_size
to be 2GB.
data "aws_iam_policy_document" "lambda_assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["lambda.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "lambda_role" {
name = "lambda_role"
assume_role_policy = data.aws_iam_policy_document.lambda_assume_role.json
}
resource "aws_lambda_function" "test_lambda" {
filename = "lambda.zip"
function_name = "checkov_lambda"
role = aws_iam_role.lambda_role.arn
handler = "index.lambda_handler"
memory_size = 2048 # Note this
runtime = "nodejs18.x"
}
In my previous article, I shared why I prefer to scan the generated plan file instead of the actual .tf files within my directory. Let’s do terraform plan and generate the JSON file.
terraform plan -out tfplan
terrform show -json tfplan | jq '.' > tfplan.json
Custom Checkov Policies
Custom Checkov policies allow us to expand on the default set of rules defined and create customised policies that suit the organisation’s needs. There are two ways to write custom policies: YAML or Python. In this article, we will be looking at the YAML implementation.
The YAML policies use a predefined set of structures and logic to craft our rules. You can read more about them here.
Based on the requirement above, if we want to enforce a maximum memory size of 2GB, this is what the YAML policy would look like. Let’s create a file called CUSTOM_YAML.yaml
with the content below and put it in a policies
folder.
metadata:
name: "Lambda Memory <=2GB"
id: "CUSTOM_YAML"
category: "GENERAL_SECURITY"
definition:
cond_type: attribute
resource_types:
- aws_lambda_function
attribute: memory_size
operator: less_than_or_equal
value: 2048
Once the file is created, Let’s run the following command to execute the check.
checkov -f tfplan.json --external-checks-dir policies --check CUSTOM_YAML
Based on this check, we should see a successful run.
Now let’s go back to our Lambda function definition and update the memory_size
to 3GB.
resource "aws_lambda_function" "test_lambda" {
filename = "lambda.zip"
function_name = "checkov_lambda"
role = aws_iam_role.lambda_role.arn
handler = "index.lambda_handler"
memory_size = 3072 # Update this
runtime = "nodejs18.x"
}
Let’s create the plan JSON file again.
terraform plan -out tfplan
terrform show -json tfplan | jq '.' > tfplan.json
Finally, let’s rerun the check.
checkov -f tfplan.json --external-checks-dir policies --check CUSTOM_YAML
This time, we can see that the check has failed.
Conclusion
In this article, we went through the basic usage of the YAML policies to write a custom rule to create customised rules for our organisation. Since Checkov is highly extendable, it can be used as effective preventive control in your CI/CD pipelines. It could either work independently or together with pre-approved Terraform modules within your organisation for a defence-in-depth strategy for compliance.