Checkov runs static code analysis on Terraform files. It will scan each resource only for policies that were defined by the policy file.
Policies are expressed as Python files and include the following:
- The type of resource to run the policy against
- The required result(s) of a specific configuration under that resource
Writing a new Policy
A policy needs to specify the following items:
name : A new policy’s unique purpose; It should ideally specify the positive desired outcome of the policy.
id: A mandatory unique identifier of a policy; Native policies written by Bridgecrew contributors will follow the following convention
supported_resources: Infrastructure objects, as described in the scanned IaC’s language; This should usually contain one specific resource block. If you support multiple resources, you can use
* to match any type of entity in that specific domain (This depends on which check base class you extend. If you extend
checkov.terraform.checks.resource.base_resource_check.BaseResourceCheck, the check is registered for all terraform resources.)
?ws_* will match anything where the second character is a
'w', the third is a
's' and the fourth is a
categories: Categorization of a scan; usually used to produce compliance reports, pipeline analytics and infrastructure health metrics, etc.
For this tutorial let’s produce a policy that ensures that new RDS services spun-up are encrypted at rest, given a scanned Terraform configuration (CKV_AWS_16).
- Start by creating a new file in the AWS check directory
- Import the following:
from checkov.common.models.enums import CheckResult, CheckCategories from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
- At this point, we define the meta entities for this check:
class RDSEncryption(BaseResourceCheck): def __init__(self): name = "Ensure all data stored in the RDS is securely encrypted at rest" id = "CKV_AWS_16" supported_resources = ['aws_db_instance'] categories = [CheckCategories.ENCRYPTION] super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
- Next we define a simple check of the
aws_db_instanceresource block to find if
aws_db_instanceis disabled. When disabled, we require it will result in a
def scan_resource_conf(self, conf): """ Looks for encryption configuration at aws_db_instance: https://www.terraform.io/docs/providers/aws/d/db_instance.html :param conf: aws_db_instance configuration :return: <CheckResult> """ if 'storage_encrypted' in conf.keys(): key = conf['storage_encrypted'] if key: return CheckResult.PASSED return CheckResult.FAILED
- Last - our file should conclude the policy name and operationalize it with this statement.
check = RDSEncryption()
Run a new scan
To run a new scan containing our newly added policy, use the
checkov -d /user/tf
Explore your scan Results and check out the supported output methods (CLI, JSON, Junit XML).