Skip to content

Instantly share code, notes, and snippets.

@skwashd
Last active March 25, 2026 03:19
Show Gist options
  • Select an option

  • Save skwashd/cef1891093b1ada799aaeacfa750648d to your computer and use it in GitHub Desktop.

Select an option

Save skwashd/cef1891093b1ada799aaeacfa750648d to your computer and use it in GitHub Desktop.
Terraform rules for agentic coding tools

Terraform Development Rules

File Structure

  • main.tf contains data sources only - never resources
  • Each module must have: main.tf, outputs.tf, versions.tf, variables.tf
  • Resources go in separate .tf files grouped by service (e.g., s3.tf, iam.tf)
  • If >20 resources in one file, split or create submodule
  • Use descriptive filenames for resource files

Variables

  • All variables must have description and type definitions
  • Complex types must define complete object structure
  • Sort variables alphabetically by name
  • Required variables: role_prefix (default: ""), role_permission_boundary_name (default: null)
  • Never use region as variable - use data.aws_region.current.name
  • Validate inputs exist using data sources in addition to validation blocks

Tagging

  • Tag all resources that support tags via tags variable
  • Top-level module must validate tags contains environment key
  • Resources without name support: merge tags with Name property

IAM

  • Always use aws_iam_policy_document data sources, never jsonencoded()ed inline JSON
  • In statements: list actions first (each on new line), then resources, then conditions
  • Omit effect = "Allow" (default)
  • Always include confused deputy conditions in assume role policies such as current account
  • Name policy documents: same as role name, or assume_<service>, or <service>_<resource>
  • Prefix all role names with var.role_prefix
  • Use permission boundary local with ternary operator defaulting to null
  • Create separate aws_iam_role, aws_iam_policy, and aws_iam_role_policy_attachment resources
  • Use the name property of the aws_iam_role as value for the name property of the aws_iam_policy resource

S3

  • Use modern S3 resources (v5+): aws_s3_bucket_acl, aws_s3_bucket_lifecycle_configuration, etc.
  • Enable access logging unless explicitly exempted
  • Validate logging bucket exists with data source
  • Never make buckets public or allow direct website hosting
  • Use CloudFront for web access

CloudWatch Logs

  • Create log groups for resources using CloudWatch logs
  • Hardcode retention to 30 days
  • Only allow logs:CreateLogStream and logs:PutLogEvents permissions

VPC & Security Groups

  • Never use vpc_id as variable - derive from first subnet provided
  • Validate subnet IDs using regex
  • Use aws_vpc_security_group_ingress_rule and aws_vpc_security_group_egress_rule resources
  • Create minimal access rules only

Validation Workflow

Run in this order:

terraform fmt -recursive
terraform validate
tflint --recursive

Code Formatting

  • Use empty lines to separate parameter groups
  • Avoid >5 spaces before equals sign - add empty line instead
  • Each list item on new line with trailing comma
  • Run terraform fmt -recursive before all commits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment