|
| 1 | +# TFLint AWS Meta Ruleset |
| 2 | + |
| 3 | +[](https://github.com/myerscode/tflint-ruleset-aws-meta/actions) |
| 4 | + |
| 5 | +A TFLint ruleset for AWS best practices, focusing on preventing hardcoded values and promoting flexible, maintainable Terraform code. |
| 6 | + |
| 7 | +This ruleset helps enforce multi-region and multi-partition compatibility by detecting hardcoded AWS regions and partitions in your Terraform configurations. It provides comprehensive coverage across IAM policies, provider configurations, and all AWS resource types where hardcoded values prevent flexible deployments. |
| 8 | + |
| 9 | +## Requirements |
| 10 | + |
| 11 | +- TFLint v0.42+ |
| 12 | +- Go v1.25 |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +TODO: This template repository does not contain release binaries, so this installation will not work. Please rewrite for your repository. See the "Building the plugin" section to get this template ruleset working. |
| 17 | + |
| 18 | +You can install the plugin with `tflint --init`. Declare a config in `.tflint.hcl` as follows: |
| 19 | + |
| 20 | +```hcl |
| 21 | +plugin "aws-multi" { |
| 22 | + enabled = true |
| 23 | +
|
| 24 | + version = "0.1.0" |
| 25 | + source = "github.com/myerscode/tflint-ruleset-aws-meta" |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +## Rules |
| 30 | + |
| 31 | +|Name|Description|Severity|Enabled|Link| |
| 32 | +| --- | --- | --- | --- | --- | |
| 33 | +|aws_iam_role_policy_hardcoded_region|Validates that there are no hardcoded AWS regions in IAM role policy documents|WARNING|✔|| |
| 34 | +|aws_iam_role_policy_hardcoded_partition|Validates that there are no hardcoded AWS partitions in IAM role policy documents|WARNING|✔|| |
| 35 | +|aws_iam_policy_hardcoded_region|Validates that there are no hardcoded AWS regions in IAM policy documents|WARNING|✔|| |
| 36 | +|aws_iam_policy_hardcoded_partition|Validates that there are no hardcoded AWS partitions in IAM policy documents|WARNING|✔|| |
| 37 | +|aws_provider_hardcoded_region|Validates that there are no hardcoded AWS regions or credentials in provider configuration|WARNING|✔|| |
| 38 | + |
| 39 | +### Rule Details |
| 40 | + |
| 41 | +#### aws_iam_role_policy_hardcoded_region |
| 42 | + |
| 43 | +This rule checks `aws_iam_role_policy` resources for hardcoded AWS regions in policy documents. It examines both JSON policy strings and structured policy documents to detect: |
| 44 | + |
| 45 | +- Hardcoded regions in ARNs within policy statements (e.g., `arn:aws:s3:::bucket/us-east-1/*`) |
| 46 | +- Direct region references in policy JSON |
| 47 | + |
| 48 | +**Example violations:** |
| 49 | +```hcl |
| 50 | +resource "aws_iam_role_policy" "bad" { |
| 51 | + policy = jsonencode({ |
| 52 | + Statement = [{ |
| 53 | + Effect = "Allow" |
| 54 | + Action = "s3:GetObject" |
| 55 | + Resource = "arn:aws:s3:::bucket/us-east-1/*" # ❌ Hardcoded region |
| 56 | + }] |
| 57 | + }) |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +**Recommended fix:** |
| 62 | +```hcl |
| 63 | +resource "aws_iam_role_policy" "good" { |
| 64 | + policy = jsonencode({ |
| 65 | + Statement = [{ |
| 66 | + Effect = "Allow" |
| 67 | + Action = "s3:GetObject" |
| 68 | + Resource = "arn:aws:s3:::bucket/${data.aws_region.current.name}/*" # ✅ Dynamic region |
| 69 | + }] |
| 70 | + }) |
| 71 | +} |
| 72 | +``` |
| 73 | + |
| 74 | +#### aws_iam_role_policy_hardcoded_partition |
| 75 | + |
| 76 | +This rule checks `aws_iam_role_policy` resources for hardcoded AWS partitions in policy documents. It detects: |
| 77 | + |
| 78 | +- Hardcoded partitions in ARNs (e.g., `arn:aws:`, `arn:aws-cn:`, `arn:aws-us-gov:`) |
| 79 | + |
| 80 | +**Example violations:** |
| 81 | +```hcl |
| 82 | +resource "aws_iam_role_policy" "bad" { |
| 83 | + policy = jsonencode({ |
| 84 | + Statement = [{ |
| 85 | + Effect = "Allow" |
| 86 | + Action = "s3:*" |
| 87 | + Resource = "arn:aws:s3:::bucket/*" # ❌ Hardcoded partition |
| 88 | + }] |
| 89 | + }) |
| 90 | +} |
| 91 | +``` |
| 92 | + |
| 93 | +**Recommended fix:** |
| 94 | +```hcl |
| 95 | +resource "aws_iam_role_policy" "good" { |
| 96 | + policy = jsonencode({ |
| 97 | + Statement = [{ |
| 98 | + Effect = "Allow" |
| 99 | + Action = "s3:*" |
| 100 | + Resource = "arn:${data.aws_partition.current.partition}:s3:::bucket/*" # ✅ Dynamic partition |
| 101 | + }] |
| 102 | + }) |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +#### aws_iam_policy_hardcoded_region |
| 107 | + |
| 108 | +This rule checks `aws_iam_policy` resources for hardcoded AWS regions in policy documents. Similar to the role policy rule, it examines: |
| 109 | + |
| 110 | +- Hardcoded regions in ARNs within policy statements |
| 111 | +- Direct region references in policy JSON |
| 112 | + |
| 113 | +**Example violations:** |
| 114 | +```hcl |
| 115 | +resource "aws_iam_policy" "bad" { |
| 116 | + policy = jsonencode({ |
| 117 | + Statement = [{ |
| 118 | + Effect = "Allow" |
| 119 | + Action = "lambda:InvokeFunction" |
| 120 | + Resource = "arn:aws:lambda:eu-west-1:123456789012:function:*" # ❌ Hardcoded region |
| 121 | + }] |
| 122 | + }) |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +**Recommended fix:** |
| 127 | +```hcl |
| 128 | +resource "aws_iam_policy" "good" { |
| 129 | + policy = jsonencode({ |
| 130 | + Statement = [{ |
| 131 | + Effect = "Allow" |
| 132 | + Action = "lambda:InvokeFunction" |
| 133 | + Resource = "arn:aws:lambda:${data.aws_region.current.name}:123456789012:function:*" # ✅ Dynamic region |
| 134 | + }] |
| 135 | + }) |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +#### aws_iam_policy_hardcoded_partition |
| 140 | + |
| 141 | +This rule checks `aws_iam_policy` resources for hardcoded AWS partitions in policy documents. It detects: |
| 142 | + |
| 143 | +- Hardcoded partitions in ARNs within policy statements |
| 144 | + |
| 145 | +**Example violations:** |
| 146 | +```hcl |
| 147 | +resource "aws_iam_policy" "bad" { |
| 148 | + policy = jsonencode({ |
| 149 | + Statement = [{ |
| 150 | + Effect = "Allow" |
| 151 | + Action = "sqs:*" |
| 152 | + Resource = "arn:aws-us-gov:sqs:*:*:*" # ❌ Hardcoded partition |
| 153 | + }] |
| 154 | + }) |
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +**Recommended fix:** |
| 159 | +```hcl |
| 160 | +resource "aws_iam_policy" "good" { |
| 161 | + policy = jsonencode({ |
| 162 | + Statement = [{ |
| 163 | + Effect = "Allow" |
| 164 | + Action = "sqs:*" |
| 165 | + Resource = "arn:${data.aws_partition.current.partition}:sqs:*:*:*" # ✅ Dynamic partition |
| 166 | + }] |
| 167 | + }) |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +#### aws_provider_hardcoded_region |
| 172 | + |
| 173 | +This rule checks AWS provider configurations for security and flexibility issues. It detects: |
| 174 | + |
| 175 | +- Hardcoded regions in provider `region` attribute |
| 176 | +- Hardcoded AWS access keys and secret keys (security risk) |
| 177 | +- Hardcoded regions in `assume_role` ARNs |
| 178 | + |
| 179 | +**Example violations:** |
| 180 | +```hcl |
| 181 | +provider "aws" { |
| 182 | + region = "us-east-1" # ❌ Hardcoded region |
| 183 | +} |
| 184 | +``` |
| 185 | + |
| 186 | +**Recommended fix:** |
| 187 | +```hcl |
| 188 | +provider "aws" { |
| 189 | + region = var.aws_region # ✅ Use variables |
| 190 | +} |
| 191 | +``` |
| 192 | + |
| 193 | + |
0 commit comments