compliance.tf

Operational Rule Definitions

Which rules run is decided before your source string gets a say. An organization host applies what that organization's admins configured. A framework host applies your own organization's Baseline when its rules state is Enforced, and ?rules= then replaces or subtracts from that set for a single download, while ?add_rules= adds to it. Either way, picking a rule starts with knowing that it exists and what it would do.

This page is that list. Every selectable rule appears below with its id, its parameters, its shipped defaults, and the transformers it runs, in the HCL the engine loads. Read the one you are considering before you put its id in a source line.

Each rule has its own anchor, so a rule can be linked to directly. lifecycle_ignore_ami_changes is /rules/definitions/#lifecycle_ignore_ami_changes.

What this page is, and what it is not

It is the list of rules you can name, with what each one would change. The definitions are rendered from the rule catalog that ships with the engine, so a change in the engine changes this page.

It is not a reusable artifact. There is no licence attached to these definitions and no grant of any kind is made. They are published so you can choose a rule, not so they can be lifted into another tool.

It is not the engine's source files byte-for-byte. See How this page is rendered.

It is not a record of what ran on a download. A module compliance.tf builds for you carries a compliancetf-manifest.json naming every rule the build received, each with an outcome saying what it actually did — a listed rule may have enforced nothing. That is the per-download record; this is the menu.

Rules are operational, not regulatory — see Operational Rules for how the two layers differ.


How this page is rendered

The definitions come from the rule catalog the engine publishes (rules-catalog.json, engine version 0.20.1), which is the engine's own serialization of its rule files. This site renders a vendored snapshot of that catalog rather than reading it live, so the version above is the snapshot's own: when it lags the engine the registry is running, a definition on this page lags with it.

Three things follow from rendering the catalog rather than copying the source files, and they matter when you are reading a definition to decide on it:

  • The intent block is not shown. It selects which blocks a rule inspects. The catalog stores a derived, lossy form of it, and reconstructing one would mean printing HCL that a rule does not have.
  • A field left at an empty or wildcard default is absent from the transformer block. The catalog drops those. The parameter table in each definition is still complete, so a parameter you see with a [] default is real even when no transformer line mentions it.
  • A value that equals a parameter's default is shown as param.<name>. That is how the rules are written, and it keeps a configurable value from reading as a hard-coded one.

The per-rule pages carry the parts a definition cannot show you: before-and-after HCL, known limits, failure modes, and the break-glass path.


Naming a rule

Append the rule id to the module source, exactly as it is written below. Nothing else about the source line changes.

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

Parameters never travel in the URL, so a rule named this way runs with the defaults printed below. Changing a parameter means configuring the rule in an organization Baseline or ruleset — see Baseline rules and rulesets.


lifecycle_ignore_ami_changes

Ignore AMI changes on EC2 instances to prevent unnecessary replacements

Severitywarning
Transformerslifecycle (safe)
PageIgnore AMI Changes
rule "lifecycle_ignore_ami_changes" {
  description = "Ignore AMI changes on EC2 instances to prevent unnecessary replacements"
  severity    = "warning"

  param "ignore_changes" {
    type        = "list(string)"
    default     = ["ami", "image_id"]
    description = "Lifecycle attributes to ignore"
  }

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_instance", "aws_launch_template"]
    description = "Target resource type patterns"
  }

  transformer "lifecycle" {
    action         = "add"
    ignore_changes = param.ignore_changes
    resource_types = param.resource_types
  }
}

lifecycle_ignore_autoscaling_changes

Ignore autoscaling-managed capacity on DynamoDB tables to prevent drift

Severitywarning
Transformerslifecycle (safe)
PageIgnore Autoscaling Changes
rule "lifecycle_ignore_autoscaling_changes" {
  description = "Ignore autoscaling-managed capacity on DynamoDB tables to prevent drift"
  severity    = "warning"

  param "ignore_changes" {
    type        = "list(string)"
    default     = ["read_capacity", "write_capacity"]
    description = "Lifecycle attributes to ignore"
  }

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_dynamodb_table"]
    description = "Target resource type patterns"
  }

  transformer "lifecycle" {
    action         = "add"
    ignore_changes = param.ignore_changes
    resource_types = param.resource_types
  }
}

lifecycle_ignore_tag_keys

Ignore drift on specific resource tag keys (e.g. an external scanner tag) via lifecycle ignore_changes, without exposing an arbitrary lifecycle value

Severitywarning
Transformerslifecycle (safe)
Familylifecycle_ignore_tags — at most one rule in a family applies to a given resource type
PageIgnore Selected Tag Keys
rule "lifecycle_ignore_tag_keys" {
  description = "Ignore drift on specific resource tag keys (e.g. an external scanner tag) via lifecycle ignore_changes, without exposing an arbitrary lifecycle value"
  severity    = "warning"
  family      = "lifecycle_ignore_tags"

  param "tag_keys" {
    type        = "list(string)"
    default     = []
    description = "AWS tag keys to ignore drift on. Each is emitted as ignore_changes = [tags[\"<key>\"]] with safe literal encoding; empty = unconfigured no-op"
  }

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_s3_bucket"]
    description = "Target resource type patterns. A module with none of these is not applicable"
  }

  transformer "lifecycle" {
    action         = "add"
    resource_types = param.resource_types
  }
}

lifecycle_ignore_tags

Ignore tag changes in lifecycle to prevent Terraform drift on managed resources

Severitywarning
Transformerslifecycle (safe)
PageIgnore Tag Changes
rule "lifecycle_ignore_tags" {
  description = "Ignore tag changes in lifecycle to prevent Terraform drift on managed resources"
  severity    = "warning"

  param "ignore_changes" {
    type        = "list(string)"
    default     = ["tags", "tags_all"]
    description = "Lifecycle attributes to ignore"
  }

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_*"]
    description = "Target resource type patterns"
  }

  transformer "lifecycle" {
    action         = "add"
    ignore_changes = param.ignore_changes
    resource_types = param.resource_types
  }
}

lifecycle_prevent_destroy_data

Prevent accidental destruction of data-storage resources (S3, RDS instances and clusters, DynamoDB, EFS, ElastiCache replication groups)

Severityerror
Transformerslifecycle (safe)
PagePrevent Destroy Data
rule "lifecycle_prevent_destroy_data" {
  description = "Prevent accidental destruction of data-storage resources (S3, RDS instances and clusters, DynamoDB, EFS, ElastiCache replication groups)"
  severity    = "error"

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_s3_bucket", "aws_db_instance", "aws_rds_cluster", "aws_dynamodb_table", "aws_efs_file_system", "aws_elasticache_replication_group"]
    description = "Data-storage resource types to protect"
  }

  transformer "lifecycle" {
    action          = "add"
    prevent_destroy = true
    resource_types  = param.resource_types
  }
}

lifecycle_prevent_destroy_encryption

Prevent destruction of KMS keys and Secrets Manager secrets

Severityerror
Transformerslifecycle (safe)
PagePrevent Destroy Encryption
rule "lifecycle_prevent_destroy_encryption" {
  description = "Prevent destruction of KMS keys and Secrets Manager secrets"
  severity    = "error"

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_kms_key", "aws_secretsmanager_secret"]
    description = "Encryption resource types to protect"
  }

  transformer "lifecycle" {
    action          = "add"
    prevent_destroy = true
    resource_types  = param.resource_types
  }
}

provisioner_remove_blocks

Remove provisioner blocks which are an anti-pattern in reusable modules

Severitywarning
Transformersblock_removal (caution)
PageNo Provisioners
rule "provisioner_remove_blocks" {
  description = "Remove provisioner blocks which are an anti-pattern in reusable modules"
  severity    = "warning"

  param "resource_types" {
    type        = "list(string)"
    default     = ["*"]
    description = "Target resource type patterns"
  }

  transformer "block_removal" {
    block_type = "provisioner"
  }
}

resource_restrict_instance_types

Restrict EC2 instance types to cost-effective options

Severityerror
Transformersattribute_restriction (safe)
PageRestrict Instance Types
rule "resource_restrict_instance_types" {
  description = "Restrict EC2 instance types to cost-effective options"
  severity    = "error"

  param "denied" {
    type        = "list(string)"
    default     = ["p3.*", "p4.*", "x1.*", "x2.*", "u-*"]
    description = "Denied instance type patterns"
  }

  param "message" {
    type        = "string"
    default     = "GPU and high-memory instance types are not permitted without approval"
    description = "Validation error message"
  }

  transformer "attribute_restriction" {
    resource_type = "aws_instance"
    attribute     = "instance_type"
    denied        = param.denied
    message       = param.message
  }
}

variable_allowed_regions

Restrict the module's region variable to an org-approved allowlist

Severityerror
Transformersvariable_assertion (safe)
PageAllowed Regions
rule "variable_allowed_regions" {
  description = "Restrict the module's region variable to an org-approved allowlist"
  severity    = "error"

  param "regions" {
    type        = "list(string)"
    default     = []
    description = "Allowed AWS regions (enumerated, no globs). Empty = unconfigured: the rule injects nothing and enforces nothing"
  }

  param "allow_unset" {
    type        = "bool"
    default     = false
    description = "Accept a null region (provider-inherited). Unenforced by consent - it does not permit a wrong region"
  }

  param "variable_name" {
    type        = "string"
    default     = "region"
    description = "Name of the module variable carrying the region"
  }

  param "resource_types" {
    type        = "list(string)"
    default     = ["aws_*"]
    description = "Resource types this rule applies to. A module with none is not applicable"
  }

  transformer "variable_assertion" {
    variable      = param.variable_name
    condition     = "var.{{variable}} == null ? {{allow_unset}} : contains({{values}}, var.{{variable}})"
    error_message = "Variable \"{{variable}}\" must be one of the regions allowed by your organization: {{values}}. An empty or unknown value is rejected."
    allow_unset   = param.allow_unset
  }
}

Rules that are not listed here

The registry also carries a small set of internal content-processing rules. They are not selectable — ?rules= does not accept them — so they are outside what this page is for, which is choosing a rule to name. They are not among the rules above and their definitions are not published.

They are not invisible either: a module compliance.tf builds for you carries a compliancetf-manifest.json naming each rule the build received, internal ones included, each with an outcome recording what it actually did.


Terraform and OpenTofu compatible

Every rule above reads ordinary HCL, and anything it changes stays ordinary HCL. Modules behave the same under Terraform (1.x+) and OpenTofu (1.6+).

On this page

Ask AI about this

Help improve this page