Skip to content

Commit 6f7f060

Browse files
authored
Add aws_iam_group_policy too long rule (#159)
* Add aws_iam_group_policy too long rule * fixed PR comments * Wrapped checks in EnsureNoError
1 parent 6c328d5 commit 6f7f060

6 files changed

+178
-5
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# aws_iam_group_policy_too_long
2+
3+
This makes sure that an IAM group policy is not longer than the 5120 AWS character limit.
4+
## Example
5+
6+
```hcl
7+
resource "aws_iam_group_policy" "policy" {
8+
name = "test_policy"
9+
group = "test_group"
10+
description = "My test policy"
11+
policy = <<EOF
12+
{
13+
STRING LONGER THAN 5120
14+
}
15+
EOF
16+
}
17+
```
18+
19+
```
20+
$ tflint
21+
1 issue(s) found:
22+
Error: The policy length is %d characters and is limited to 5120 characters. (aws_iam_policy_too_long_policy)
23+
on template.tf line 6:
24+
6: policy = "{POLICY}" // Policy is too long,!
25+
26+
```
27+
28+
## Why
29+
30+
Terraform does not check against this rule, but it will error if an apply is attempted. https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-quotas-entity-length
31+
32+
## How To Fix
33+
34+
Update policy to reduce characters. Some methods are splitting into multiple policies, or switching to using a combination of deny and allow statements to optimize the policy.

docs/rules/aws_iam_policy_too_long_policy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# aws_iam_policy_too_long_policy
22

3-
This makes sure that a IAM policy is not longer than the 6144 AWS character limit.
3+
This makes sure that an IAM policy is not longer than the 6144 AWS character limit.
44

55
## Example
66

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package rules
2+
3+
import (
4+
"fmt"
5+
hcl "github.com/hashicorp/hcl/v2"
6+
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
7+
"github.com/terraform-linters/tflint-ruleset-aws/project"
8+
"regexp"
9+
)
10+
11+
// AwsIAMGroupPolicyTooLongRule checks that the policy length is less than 5,120 characters
12+
type AwsIAMGroupPolicyTooLongRule struct {
13+
resourceType string
14+
attributeName string
15+
whitespaceRegex *regexp.Regexp
16+
}
17+
18+
// NewAwsIAMGroupPolicyTooLongRule returns new rule with default attributes
19+
func NewAwsIAMGroupPolicyTooLongRule() *AwsIAMGroupPolicyTooLongRule {
20+
return &AwsIAMGroupPolicyTooLongRule{
21+
resourceType: "aws_iam_group_policy",
22+
attributeName: "policy",
23+
whitespaceRegex: regexp.MustCompile(`\s+`),
24+
}
25+
}
26+
27+
// Name returns the rule name
28+
func (r *AwsIAMGroupPolicyTooLongRule) Name() string {
29+
return "aws_iam_group_policy_too_long"
30+
}
31+
32+
// Enabled returns whether the rule is enabled by default
33+
func (r *AwsIAMGroupPolicyTooLongRule) Enabled() bool {
34+
return true
35+
}
36+
37+
// Severity returns the rule severity
38+
func (r *AwsIAMGroupPolicyTooLongRule) Severity() string {
39+
return tflint.ERROR
40+
}
41+
42+
// Link returns the rule reference link
43+
func (r *AwsIAMGroupPolicyTooLongRule) Link() string {
44+
return project.ReferenceLink(r.Name())
45+
}
46+
47+
// Check checks the length of the policy
48+
func (r *AwsIAMGroupPolicyTooLongRule) Check(runner tflint.Runner) error {
49+
return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error {
50+
var policy string
51+
err := runner.EvaluateExpr(attribute.Expr, &policy, nil)
52+
return runner.EnsureNoError(err, func() error {
53+
policy = r.whitespaceRegex.ReplaceAllString(policy, "")
54+
if len(policy) > 5120 {
55+
runner.EmitIssueOnExpr(
56+
r,
57+
fmt.Sprintf("The policy length is %d characters and is limited to 5120 characters.", len(policy)),
58+
attribute.Expr,
59+
)
60+
}
61+
return nil
62+
})
63+
})
64+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package rules
2+
3+
import (
4+
"math/rand"
5+
"testing"
6+
"time"
7+
8+
hcl "github.com/hashicorp/hcl/v2"
9+
"github.com/terraform-linters/tflint-plugin-sdk/helper"
10+
)
11+
12+
func AwsIAMGroupPolicyTooLongRandSeq(n int) string {
13+
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
14+
b := make([]rune, n)
15+
for i := range b {
16+
b[i] = letters[rand.Intn(len(letters))]
17+
}
18+
return string(b)
19+
}
20+
21+
func Test_AwsIAMGroupPolicyTooLong(t *testing.T) {
22+
rand.Seed(time.Now().UnixNano())
23+
cases := []struct {
24+
Name string
25+
Content string
26+
Expected helper.Issues
27+
}{
28+
{
29+
Name: "policy is too long",
30+
Content: `
31+
resource "aws_iam_group_policy" "policy" {
32+
name = "test_policy"
33+
group = "test_group"
34+
policy = <<EOF
35+
{
36+
"Version": "2012-10-17",
37+
"Statement": [
38+
{
39+
"Action": [
40+
` + AwsIAMGroupPolicyTooLongRandSeq(5120) + `
41+
],
42+
"Effect": "Allow",
43+
"Resource": "arn:aws:s3:::<bucketname>/*""
44+
}
45+
]
46+
}
47+
EOF
48+
}
49+
`,
50+
Expected: helper.Issues{
51+
{
52+
Rule: NewAwsIAMGroupPolicyTooLongRule(),
53+
Message: "The policy length is 5231 characters and is limited to 5120 characters.",
54+
Range: hcl.Range{
55+
Filename: "resource.tf",
56+
Start: hcl.Pos{Line: 5, Column: 11},
57+
End: hcl.Pos{Line: 18, Column: 4},
58+
},
59+
},
60+
},
61+
},
62+
}
63+
64+
rule := NewAwsIAMGroupPolicyTooLongRule()
65+
66+
for _, tc := range cases {
67+
runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content})
68+
69+
if err := rule.Check(runner); err != nil {
70+
t.Fatalf("Unexpected error occurred: %s", err)
71+
}
72+
73+
helper.AssertIssues(t, tc.Expected, runner.Issues)
74+
}
75+
}

rules/aws_iam_policy_too_long_policy_test.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import (
99
"github.com/terraform-linters/tflint-plugin-sdk/helper"
1010
)
1111

12-
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
13-
14-
func randSeq(n int) string {
12+
func AwsIAMPolicyTooLongPolicyRandSeq(n int) string {
13+
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
1514
b := make([]rune, n)
1615
for i := range b {
1716
b[i] = letters[rand.Intn(len(letters))]
@@ -39,7 +38,7 @@ resource "aws_iam_policy" "policy" {
3938
"Statement": [
4039
{
4140
"Action": [
42-
` + randSeq(6034) + `
41+
` + AwsIAMPolicyTooLongPolicyRandSeq(6034) + `
4342
],
4443
"Effect": "Allow",
4544
"Resource": "arn:aws:s3:::<bucketname>/*""

rules/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@ var Rules = append([]tflint.Rule{
3535
NewAwsIAMPolicySidInvalidCharactersRule(),
3636
NewAwsIAMPolicyTooLongPolicyRule(),
3737
NewAwsLambdaFunctionDeprecatedRuntimeRule(),
38+
NewAwsIAMGroupPolicyTooLongRule(),
3839
}, models.Rules...)

0 commit comments

Comments
 (0)