Skip to content

Commit

Permalink
aws_iam_policy_length (#153)
Browse files Browse the repository at this point in the history
* aws_iam_policy_length -  Added a rule to check against IAM policy length. fixes #26

* formated

* Update name of rule, update character count, ignore whitespace
  • Loading branch information
Rihoj authored Aug 11, 2021
1 parent ccdd4aa commit 8047cf5
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 2 deletions.
35 changes: 35 additions & 0 deletions docs/rules/aws_iam_policy_too_long_policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# aws_iam_policy_too_long_policy

This makes sure that a IAM policy is not longer than the 6144 AWS character limit.

## Example

```hcl
resource "aws_iam_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
policy = <<EOF
{
STRING LONGER THAN 6144
}
EOF
}
```

```
$ tflint
1 issue(s) found:
Error: The policy length is %d characters and is limited to 6144 characters. (aws_iam_policy_too_long_policy)
on template.tf line 6:
6: policy = "{POLICY}" // Policy is too long,!
```

## Why

Terraform does not check against this rule, but it will error if an apply is attempted.

## How To Fix

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.
5 changes: 3 additions & 2 deletions rules/aws_iam_policy_sid_invalid_characters.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package rules

import (
"encoding/json"
"fmt"
hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/terraform-linters/tflint-ruleset-aws/project"
"regexp"
"fmt"
)

type AwsIAMPolicySidInvalidCharactersStatementStruct struct {
Sid string `json:"Sid"`
}
Expand Down Expand Up @@ -58,7 +59,7 @@ func (r *AwsIAMPolicySidInvalidCharactersRule) Check(runner tflint.Runner) error
err := runner.EvaluateExpr(attribute.Expr, &val, nil)
unMarshaledPolicy := AwsIAMPolicySidInvalidCharactersPolicyStruct{}
if jsonErr := json.Unmarshal([]byte(val), &unMarshaledPolicy); jsonErr != nil {
return jsonErr;
return jsonErr
}
statements := unMarshaledPolicy.Statement

Expand Down
63 changes: 63 additions & 0 deletions rules/aws_iam_policy_too_long_policy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package rules

import (
"fmt"
hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
"github.com/terraform-linters/tflint-ruleset-aws/project"
"regexp"
)

// AwsIAMPolicyTooLongPolicyRule checks that the policy length is less than 6,144 characters
type AwsIAMPolicyTooLongPolicyRule struct {
resourceType string
attributeName string
}

// NewAwsIAMPolicyTooLongPolicyRule returns new rule with default attributes
func NewAwsIAMPolicyTooLongPolicyRule() *AwsIAMPolicyTooLongPolicyRule {
return &AwsIAMPolicyTooLongPolicyRule{
resourceType: "aws_iam_policy",
attributeName: "policy",
}
}

// Name returns the rule name
func (r *AwsIAMPolicyTooLongPolicyRule) Name() string {
return "aws_iam_policy_too_long_policy"
}

// Enabled returns whether the rule is enabled by default
func (r *AwsIAMPolicyTooLongPolicyRule) Enabled() bool {
return true
}

// Severity returns the rule severity
func (r *AwsIAMPolicyTooLongPolicyRule) Severity() string {
return tflint.ERROR
}

// Link returns the rule reference link
func (r *AwsIAMPolicyTooLongPolicyRule) Link() string {
return project.ReferenceLink(r.Name())
}

// Check checks the length of the policy
func (r *AwsIAMPolicyTooLongPolicyRule) Check(runner tflint.Runner) error {
return runner.WalkResourceAttributes(r.resourceType, r.attributeName, func(attribute *hcl.Attribute) error {
var policy string
err := runner.EvaluateExpr(attribute.Expr, &policy, nil)
whitespaceRegex := regexp.MustCompile(`\s+`)
policy = whitespaceRegex.ReplaceAllString(policy, "")
return runner.EnsureNoError(err, func() error {
if len(policy) > 6144 {
runner.EmitIssueOnExpr(
r,
fmt.Sprintf("The policy length is %d characters and is limited to 6144 characters.", len(policy)),
attribute.Expr,
)
}
return nil
})
})
}
77 changes: 77 additions & 0 deletions rules/aws_iam_policy_too_long_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package rules

import (
"math/rand"
"testing"
"time"

hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/helper"
)

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randSeq(n int) string {
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}

func Test_AwsIAMPolicyTooLongPolicy(t *testing.T) {
rand.Seed(time.Now().UnixNano())
cases := []struct {
Name string
Content string
Expected helper.Issues
}{
{
Name: "policy is too long",
Content: `
resource "aws_iam_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
` + randSeq(6034) + `
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::<bucketname>/*""
}
]
}
EOF
}
`,
Expected: helper.Issues{
{
Rule: NewAwsIAMPolicyTooLongPolicyRule(),
Message: "The policy length is 6145 characters and is limited to 6144 characters.",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 6, Column: 11},
End: hcl.Pos{Line: 19, Column: 4},
},
},
},
},
}

rule := NewAwsIAMPolicyTooLongPolicyRule()

for _, tc := range cases {
runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content})

if err := rule.Check(runner); err != nil {
t.Fatalf("Unexpected error occurred: %s", err)
}

helper.AssertIssues(t, tc.Expected, runner.Issues)
}
}
1 change: 1 addition & 0 deletions rules/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ var Rules = append([]tflint.Rule{
NewAwsElastiCacheReplicationGroupInvalidTypeRule(),
NewAwsElastiCacheReplicationGroupPreviousTypeRule(),
NewAwsIAMPolicySidInvalidCharactersRule(),
NewAwsIAMPolicyTooLongPolicyRule(),
}, models.Rules...)

0 comments on commit 8047cf5

Please sign in to comment.