tfsec allows you to implement custom security policies using the Rego language. This is useful for enforcing organization-specific security standards or best practices.
Policy Requirements
- Namespace: The
package name must start with the custom namespace (e.g., package custom.aws.s3.rules) for tfsec to recognize it. - Rule Naming: Rule names must be exactly
deny or must start with the prefix deny_ to ensure issues are highlighted during scans. - Input Structure: The
input variable contains cloud resources organized by provider and service (e.g., input.aws.s3.buckets). All property names are converted to lower-case. - Metadata Handling: Properties (like
bucket.name) are objects containing metadata. To check the actual value, use the .value suffix (e.g., bucket.name.value). - Reporting Results: Use the
result.new(msg, source) function to create the result object. This ensures tfsec can report the correct file path and line number.msg: A string explaining the issue.source: The property or object where the violation occurred.- Note: If no meaningful source exists, you can return a simple string instead.
Inspecting the Input Schema
To understand the structure of the input variable for your specific project, run tfsec with the --print-rego-input flag. You can pipe this to jq to explore the JSON structure:
tfsec --print-rego-input | jq '.aws.s3.buckets[0].name'
package custom.aws.s3.no_insecure_buckets
import data.lib.result
deny[res] {
bucket := input.aws.s3.buckets[_]
bucket.name.value == "insecure-bucket"
msg := "Bucket name should not be 'insecure-bucket'"
res := result.new(msg, bucket.name)
}