Skip to content

Commit fdc5acc

Browse files
authored
Add aws_security_group_rule_invalid_protocol rule (#355)
* Add aws_security_group_rule_invalid_protocol rule * Fix allowed protocols * Update README.md
1 parent 929e617 commit fdc5acc

6 files changed

+198
-0
lines changed

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ These rules warn of possible errors that can occur at `terraform apply`. Rules m
5151
|aws_s3_bucket_invalid_acl|Disallow invalid ACL rule for S3 bucket|||
5252
|aws_s3_bucket_invalid_region|Disallow invalid region for S3 bucket|||
5353
|aws_spot_fleet_request_invalid_excess_capacity_termination_policy|Disallow invalid excess capacity termination policy|||
54+
|[aws_security_group_rule_invalid_protocol](aws_security_group_rule_invalid_protocol.md)|Disallow using invalid protocol|||
5455

5556
### Best Practices/Naming Conventions
5657

docs/rules/README.md.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ These rules warn of possible errors that can occur at `terraform apply`. Rules m
5151
|aws_s3_bucket_invalid_acl|Disallow invalid ACL rule for S3 bucket||✔|
5252
|aws_s3_bucket_invalid_region|Disallow invalid region for S3 bucket||✔|
5353
|aws_spot_fleet_request_invalid_excess_capacity_termination_policy|Disallow invalid excess capacity termination policy||✔|
54+
|[aws_security_group_rule_invalid_protocol](aws_security_group_rule_invalid_protocol.md)|Disallow using invalid protocol||✔|
5455

5556
### Best Practices/Naming Conventions
5657

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# aws_security_group_rule_invalid_protocol
2+
3+
Disallow using invalid protocol.
4+
5+
## Example
6+
7+
```hcl
8+
resource "aws_security_group_rule" "sample" {
9+
type = "ingress"
10+
from_port = 443
11+
to_port = 443
12+
protocol = "https"
13+
}
14+
```
15+
16+
```
17+
$ tflint
18+
1 issue(s) found:
19+
20+
Error: "https" is an invalid protocol. (aws_security_group_rule_invalid_protocol)
21+
22+
on terraform.tf line 5:
23+
5: protocol = "https"
24+
```
25+
26+
27+
## Why
28+
29+
Apply will fail. (Plan will succeed with the invalid value though)
30+
31+
## How To Fix
32+
33+
Select valid protocol according to the [document](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SecurityGroupRule.html)
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package rules
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
9+
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
10+
"github.com/terraform-linters/tflint-ruleset-aws/project"
11+
)
12+
13+
// AwsSecurityGroupRuleInvalidProtocolRule checks whether "protocol" has invalid value
14+
type AwsSecurityGroupRuleInvalidProtocolRule struct {
15+
tflint.DefaultRule
16+
17+
resourceType string
18+
attributeName string
19+
protocols map[string]struct{}
20+
}
21+
22+
// NewAwsSecurityGroupRuleInvalidProtocolRule returns new rule with default attributes
23+
func NewAwsSecurityGroupRuleInvalidProtocolRule() *AwsSecurityGroupRuleInvalidProtocolRule {
24+
return &AwsSecurityGroupRuleInvalidProtocolRule{
25+
resourceType: "aws_security_group_rule",
26+
attributeName: "protocol",
27+
protocols: map[string]struct{}{
28+
"all": {},
29+
"tcp": {},
30+
"udp": {},
31+
"icmp": {},
32+
"icmpv6": {},
33+
},
34+
}
35+
}
36+
37+
// Name returns the rule name
38+
func (r *AwsSecurityGroupRuleInvalidProtocolRule) Name() string {
39+
return "aws_security_group_rule_invalid_protocol"
40+
}
41+
42+
// Enabled returns whether the rule is enabled by default
43+
func (r *AwsSecurityGroupRuleInvalidProtocolRule) Enabled() bool {
44+
return true
45+
}
46+
47+
// Severity returns the rule severity
48+
func (r *AwsSecurityGroupRuleInvalidProtocolRule) Severity() tflint.Severity {
49+
return tflint.ERROR
50+
}
51+
52+
// Link returns the rule reference link
53+
func (r *AwsSecurityGroupRuleInvalidProtocolRule) Link() string {
54+
return project.ReferenceLink(r.Name())
55+
}
56+
57+
// Check checks whether "protocol" has invalid value
58+
func (r *AwsSecurityGroupRuleInvalidProtocolRule) Check(runner tflint.Runner) error {
59+
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
60+
Attributes: []hclext.AttributeSchema{
61+
{Name: r.attributeName},
62+
},
63+
}, nil)
64+
if err != nil {
65+
return err
66+
}
67+
68+
for _, resource := range resources.Blocks {
69+
attribute, exists := resource.Body.Attributes[r.attributeName]
70+
if !exists {
71+
continue
72+
}
73+
74+
var protocol string
75+
err := runner.EvaluateExpr(attribute.Expr, &protocol, nil)
76+
77+
err = runner.EnsureNoError(err, func() error {
78+
if _, err := strconv.Atoi(protocol); err == nil {
79+
return nil
80+
}
81+
if _, ok := r.protocols[strings.ToLower(protocol)]; !ok {
82+
runner.EmitIssue(
83+
r,
84+
fmt.Sprintf("\"%s\" is an invalid protocol.", protocol),
85+
attribute.Expr.Range(),
86+
)
87+
}
88+
return nil
89+
})
90+
if err != nil {
91+
return err
92+
}
93+
}
94+
95+
return nil
96+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package rules
2+
3+
import (
4+
"testing"
5+
6+
hcl "github.com/hashicorp/hcl/v2"
7+
"github.com/terraform-linters/tflint-plugin-sdk/helper"
8+
)
9+
10+
func Test_AwsSecurityGroupRuleInvalidProtocol(t *testing.T) {
11+
cases := []struct {
12+
Name string
13+
Content string
14+
Expected helper.Issues
15+
}{
16+
{
17+
Name: "valid protocol",
18+
Content: `
19+
resource "aws_security_group_rule" "this" {
20+
protocol = "tcp"
21+
}
22+
`,
23+
Expected: helper.Issues{},
24+
},
25+
{
26+
Name: "valid number as protocol",
27+
Content: `
28+
resource "aws_security_group_rule" "this" {
29+
protocol = "-1"
30+
}
31+
`,
32+
Expected: helper.Issues{},
33+
},
34+
{
35+
Name: "invalid protocol",
36+
Content: `
37+
resource "aws_security_group_rule" "this" {
38+
protocol = "http"
39+
}
40+
`,
41+
Expected: helper.Issues{
42+
{
43+
Rule: NewAwsSecurityGroupRuleInvalidProtocolRule(),
44+
Message: "\"http\" is an invalid protocol.",
45+
Range: hcl.Range{
46+
Filename: "resource.tf",
47+
Start: hcl.Pos{Line: 3, Column: 16},
48+
End: hcl.Pos{Line: 3, Column: 22},
49+
},
50+
},
51+
},
52+
},
53+
}
54+
55+
rule := NewAwsSecurityGroupRuleInvalidProtocolRule()
56+
57+
for _, tc := range cases {
58+
runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content})
59+
60+
if err := rule.Check(runner); err != nil {
61+
t.Fatalf("Unexpected error occurred: %s", err)
62+
}
63+
64+
helper.AssertIssues(t, tc.Expected, runner.Issues)
65+
}
66+
}

rules/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ var manualRules = []tflint.Rule{
3838
NewAwsIAMGroupPolicyTooLongRule(),
3939
NewAwsAcmCertificateLifecycleRule(),
4040
NewAwsElasticBeanstalkEnvironmentInvalidNameFormatRule(),
41+
NewAwsSecurityGroupRuleInvalidProtocolRule(),
4142
}
4243

4344
// Rules is a list of all rules

0 commit comments

Comments
 (0)