Skip to content

Commit 69c3f2b

Browse files
samhpickeringsamhpickeringwata727
authored
aws_elastic_beanstalk_environment_invalid_name_format (#315)
* add aws_elastic_beanstalk_environment_name_invalid_format rule & tests * increase readability of error message * add documentation * add rule reference link * standardise rule name * add missing link in rules readme * break lines in readme code blocks * update example resource config * update readme description * update readme * import project for rule reference link * revert changes to rules readme * Revert "revert changes to rules readme" This reverts commit 36d962a. * Fix docs/rules/README.md.tmpl Co-authored-by: samhpickering <[email protected]> Co-authored-by: wata_mac <[email protected]>
1 parent fc2b8fe commit 69c3f2b

6 files changed

+214
-0
lines changed

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ These rules warn of possible errors that can occur at `terraform apply`. Rules m
1818
|[aws_db_instance_invalid_type](aws_db_instance_invalid_type.md)|Disallow using invalid instance class|||
1919
|aws_db_instance_invalid_vpc_security_group|Disallow using invalid VPC security groups|||
2020
|aws_dynamodb_table_invalid_stream_view_type|Disallow using invalid stream view types for DynamoDB|||
21+
|[aws_elastic_beanstalk_environment_invalid_name_format](aws_elastic_beanstalk_environment_invalid_name_format.md)|Disallow invalid environment name|||
2122
|aws_elasticache_cluster_invalid_parameter_group|Disallow using invalid parameter group|||
2223
|aws_elasticache_cluster_invalid_security_group|Disallow using invalid security groups|||
2324
|aws_elasticache_cluster_invalid_subnet_group|Disallow using invalid subnet group|||

docs/rules/README.md.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ These rules warn of possible errors that can occur at `terraform apply`. Rules m
1818
|[aws_db_instance_invalid_type](aws_db_instance_invalid_type.md)|Disallow using invalid instance class||✔|
1919
|aws_db_instance_invalid_vpc_security_group|Disallow using invalid VPC security groups|✔|✔|
2020
|aws_dynamodb_table_invalid_stream_view_type|Disallow using invalid stream view types for DynamoDB||✔|
21+
|[aws_elastic_beanstalk_environment_invalid_name_format](aws_elastic_beanstalk_environment_invalid_name_format.md)|Disallow invalid environment name||✔|
2122
|aws_elasticache_cluster_invalid_parameter_group|Disallow using invalid parameter group|✔|✔|
2223
|aws_elasticache_cluster_invalid_security_group|Disallow using invalid security groups|✔|✔|
2324
|aws_elasticache_cluster_invalid_subnet_group|Disallow using invalid subnet group|✔|✔|
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# aws_elastic_beanstalk_environment_invalid_name_format
2+
3+
Disallow invalid Elastic Beanstalk environment name
4+
5+
## Example
6+
7+
```hcl
8+
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
9+
name = "env_name_underscores"
10+
application = "example-app"
11+
solution_stack_name = "64bit Amazon Linux 2015.03 v2.0.3 running Go 1.4"
12+
}
13+
```
14+
15+
```
16+
$ tflint
17+
1 issue(s) found:
18+
19+
Error: env_name_underscores does not match constraint: must contain only letters, digits, and
20+
the dash character and may not start or end with a dash
21+
(^[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]$) (aws_elastic_beanstalk_environment_invalid_name_format)
22+
23+
on example.tf line 2:
24+
2: name = "env_name_underscores"
25+
26+
```
27+
28+
## Why
29+
30+
When attempting to create the resource, Terraform will return the error:
31+
```
32+
Error: InvalidParameterValue: Value env_name_underscores at 'EnvironmentName' failed to satisfy
33+
constraint: Member must contain only letters, digits, and the dash character and may not start
34+
or end with a dash
35+
status code: 400
36+
```
37+
38+
## How To Fix
39+
40+
Ensure your environment name consists only of letters, digits, and the dash character, and does
41+
not start or end with a dash.
42+
The regex used is `^[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]$`
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package rules
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
7+
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
8+
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
9+
"github.com/terraform-linters/tflint-ruleset-aws/project"
10+
)
11+
12+
// AwsElasticBeanstalkEnvironmentInvalidNameFormatRule checks EB environment name matches a pattern
13+
type AwsElasticBeanstalkEnvironmentInvalidNameFormatRule struct {
14+
tflint.DefaultRule
15+
16+
resourceType string
17+
attributeName string
18+
pattern *regexp.Regexp
19+
}
20+
21+
// NewAwsElasticBeanstalkEnvironmentInvalidNameFormatRule returns new rule with default attributes
22+
func NewAwsElasticBeanstalkEnvironmentInvalidNameFormatRule() *AwsElasticBeanstalkEnvironmentInvalidNameFormatRule {
23+
return &AwsElasticBeanstalkEnvironmentInvalidNameFormatRule{
24+
resourceType: "aws_elastic_beanstalk_environment",
25+
attributeName: "name",
26+
pattern: regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]$"),
27+
}
28+
}
29+
30+
// Name returns the rule name
31+
func (r *AwsElasticBeanstalkEnvironmentInvalidNameFormatRule) Name() string {
32+
return "aws_elastic_beanstalk_environment_invalid_name_format"
33+
}
34+
35+
// Enabled returns whether the rule is enabled by default
36+
func (r *AwsElasticBeanstalkEnvironmentInvalidNameFormatRule) Enabled() bool {
37+
return true
38+
}
39+
40+
// Severity returns the rule severity
41+
func (r *AwsElasticBeanstalkEnvironmentInvalidNameFormatRule) Severity() tflint.Severity {
42+
return tflint.ERROR
43+
}
44+
45+
// Link returns the rule reference link
46+
func (r *AwsElasticBeanstalkEnvironmentInvalidNameFormatRule) Link() string {
47+
return project.ReferenceLink(r.Name())
48+
}
49+
50+
// Check checks the environment name matches the pattern provided
51+
func (r *AwsElasticBeanstalkEnvironmentInvalidNameFormatRule) Check(runner tflint.Runner) error {
52+
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
53+
Attributes: []hclext.AttributeSchema{{Name: r.attributeName}},
54+
}, nil)
55+
if err != nil {
56+
return err
57+
}
58+
59+
for _, resource := range resources.Blocks {
60+
attribute, exists := resource.Body.Attributes[r.attributeName]
61+
if !exists {
62+
continue
63+
}
64+
65+
var val string
66+
err := runner.EvaluateExpr(attribute.Expr, &val, nil)
67+
68+
err = runner.EnsureNoError(err, func() error {
69+
if !r.pattern.MatchString(val) {
70+
runner.EmitIssue(
71+
r,
72+
fmt.Sprintf(`%s does not match constraint: must contain only letters, digits, and the dash `+
73+
`character and may not start or end with a dash (^[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]$)`, val),
74+
attribute.Expr.Range(),
75+
)
76+
}
77+
return nil
78+
})
79+
if err != nil {
80+
return err
81+
}
82+
}
83+
84+
return nil
85+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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_AwsElasticBeanstalkEnvironmentInvalidNameFormat(t *testing.T) {
11+
cases := []struct {
12+
Name string
13+
Content string
14+
Expected helper.Issues
15+
}{
16+
{
17+
Name: "tf-test-name dash valid",
18+
Content: `
19+
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
20+
name = "tf-test-name"
21+
application = "tf-test-name"
22+
solution_stack_name = "64bit Amazon Linux 2015.03 v2.0.3 running Go 1.4"
23+
}
24+
`,
25+
Expected: helper.Issues{},
26+
},
27+
{
28+
Name: "underscores invalid",
29+
Content: `
30+
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
31+
name = "tf_test_name"
32+
application = "tf-test-name"
33+
solution_stack_name = "64bit Amazon Linux 2015.03 v2.0.3 running Go 1.4"
34+
}
35+
`,
36+
Expected: helper.Issues{
37+
{
38+
Rule: NewAwsElasticBeanstalkEnvironmentInvalidNameFormatRule(),
39+
Message: "tf_test_name does not match constraint: must contain only letters, digits, and " +
40+
"the dash character and may not start or end with a dash (^[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]$)",
41+
Range: hcl.Range{
42+
Filename: "resource.tf",
43+
Start: hcl.Pos{Line: 3, Column: 24},
44+
End: hcl.Pos{Line: 3, Column: 38},
45+
},
46+
},
47+
},
48+
},
49+
{
50+
Name: "end with dash invalid",
51+
Content: `
52+
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
53+
name = "tf-test-name-"
54+
application = "tf-test-name"
55+
solution_stack_name = "64bit Amazon Linux 2015.03 v2.0.3 running Go 1.4"
56+
}
57+
`,
58+
Expected: helper.Issues{
59+
{
60+
Rule: NewAwsElasticBeanstalkEnvironmentInvalidNameFormatRule(),
61+
Message: "tf-test-name- does not match constraint: must contain only letters, digits, and " +
62+
"the dash character and may not start or end with a dash (^[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]$)",
63+
Range: hcl.Range{
64+
Filename: "resource.tf",
65+
Start: hcl.Pos{Line: 3, Column: 24},
66+
End: hcl.Pos{Line: 3, Column: 39},
67+
},
68+
},
69+
},
70+
},
71+
}
72+
73+
rule := NewAwsElasticBeanstalkEnvironmentInvalidNameFormatRule()
74+
75+
for _, tc := range cases {
76+
runner := helper.TestRunner(t, map[string]string{"resource.tf": tc.Content})
77+
78+
if err := rule.Check(runner); err != nil {
79+
t.Fatalf("Unexpected error occurred: %s", err)
80+
}
81+
82+
helper.AssertIssues(t, tc.Expected, runner.Issues)
83+
}
84+
}

rules/provider.go

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

0 commit comments

Comments
 (0)