Skip to content

Getting Started with Operational Rules

From viewing available rules to verifying they are applied. Typically under 5 minutes.

Prerequisites

Before you begin, make sure you have:

  • A compliance.tf account. Start a free trial or sign in.
  • Terraform >= 1.0 or OpenTofu >= 1.6 installed.
  • A module source pointing at a compliance.tf registry endpoint (e.g., soc2.compliance.tf/...). See Get Started if you have not set this up yet.
  • An access token configured via terraform login or .terraformrc. See Get Started for details.

Step 1: Browse available rules

Browse the full catalog of available rules at Rule Catalog. Each rule page shows what the rule does, which resources it affects, and example before/after HCL.

The 7 builtin rules are:

RuleWhat it does
pofix/prevent_destroy_dataAdds prevent_destroy = true to data-bearing resources (S3, RDS, DynamoDB, EFS)
pofix/ignore_tag_changesAdds ignore_changes = [tags, tags_all] to all resources
pofix/ignore_autoscaling_changesAdds ignore_changes = [read_capacity, write_capacity] to DynamoDB tables
pofix/ignore_ami_changesAdds ignore_changes = [ami] to EC2 instances
pofix/prevent_destroy_encryptionAdds prevent_destroy = true to KMS keys and Secrets Manager secrets
pofix/no_provisionersRemoves all provisioner blocks from resources
pofix/restrict_instance_typesDenies GPU and specialty instance types (p3, p4, x1, x2, u-*)

Step 2: Add rules to your module source

The simplest way to apply rules is to add the ?rules= query parameter to your HTTPS module source URL. No API calls needed. Just add the rules you want directly in your Terraform configuration:

module "s3_bucket" {
  source = "https://soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws?version=5.0.0&rules=pofix/prevent_destroy_data,pofix/ignore_tag_changes,pofix/no_provisioners"
}

This works on all tiers and gives you per-module control over which rules are applied.

Paid tier: org-level defaults. On paid tiers, org admins can configure default rules for the entire organization via the compliance.tf API (PUT app.compliance.tf/api/org/rules with session auth). When org defaults are configured, rules are applied automatically to every module download without needing ?rules= in the URL. Individual developers can still override org defaults per-request using ?rules=.

Applying rules

On all tiers, you can apply rules per-request by adding ?rules= to your module source URL. Paid tiers additionally support org-level default configuration via the API.


Step 3: Verify rules are applied

Run terraform init on any module sourced from the compliance.tf registry:

terraform init -upgrade

Expected output:

Initializing modules...
Downloading soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws 5.0.0 for s3_bucket...
- s3_bucket in .terraform/modules/s3_bucket

Initializing provider plugins...

Terraform has been successfully initialized!

After init completes, inspect the downloaded module to confirm rules were applied. For example, if you enabled Prevent Destroy Data, check the S3 bucket resource:

grep -A2 "prevent_destroy" .terraform/modules/s3_bucket/main.tf

Expected output:

  lifecycle {
    prevent_destroy = true
  }

The lifecycle block is now in the module source code. It was not there in the upstream terraform-aws-modules version.


Step 4: Inspect the rules manifest (coming soon)

Coming Soon

A .ctf-rules-manifest.json file will be included in every downloaded module, recording which rules were applied, which resources were affected, and a SHA-256 ruleset hash. This feature is planned but not yet available.


Troubleshooting

terraform init succeeds but I do not see lifecycle blocks in the downloaded module

Check that your module source URL includes the ?rules= parameter with the rules you want, or that your org has rules configured via the compliance.tf API (app.compliance.tf/api/org/rules with session auth).

If neither is set, no rules will be applied. This issue can also occur when the module was cached from a previous download. Run terraform init -upgrade to force a fresh download.

A rule and a compliance control seem to affect the same resource

Controls run first, rules run second. If both affect the same attribute, changes are merged additively (e.g., both adding entries to ignore_changes). Explicit conflict detection, where a rule contradicts a control, is planned for a future release. If you see unexpected behavior, adjust your rule configuration to avoid overlap with the control.

Rules are applied but I want to exclude a specific rule for one module

Use the per-request override in the module source URL:

module "s3_bucket" {
  source = "https://soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws?version=5.0.0&rules=-pofix/prevent_destroy_data"
}

The - prefix removes a rule for this specific download. The + prefix adds a rule that is not in your org defaults.

I get a 401 or 403 error when calling the rules API

Verify your access token is valid and has not expired. Get a new token from the Access Tokens page. Org rule configuration requires org admin permissions, so check that your account has the appropriate role.