From 4fae553b7c5b91b81b98f238b909cc295045f9e8 Mon Sep 17 00:00:00 2001 From: Preben Huybrechts Date: Thu, 31 Oct 2024 12:51:17 +0100 Subject: [PATCH] feat: azurerm_storage_account_tls_version --- go.mod | 5 +- go.sum | 2 + main.go | 9 +- rules/aws_instance_example_type.go | 75 --------------- rules/aws_instance_example_type_test.go | 49 ---------- rules/aws_s3_bucket_example_lifecycle_rule.go | 81 ---------------- ...s_s3_bucket_example_lifecycle_rule_test.go | 74 --------------- rules/azurerm_storage_account_tls_version.go | 92 +++++++++++++++++++ rules/google_compute_ssl_policy.go | 87 ------------------ rules/google_compute_ssl_policy_test.go | 68 -------------- rules/terraform_backend_type.go | 76 --------------- rules/terraform_backend_type_test.go | 53 ----------- 12 files changed, 101 insertions(+), 570 deletions(-) delete mode 100644 rules/aws_instance_example_type.go delete mode 100644 rules/aws_instance_example_type_test.go delete mode 100644 rules/aws_s3_bucket_example_lifecycle_rule.go delete mode 100644 rules/aws_s3_bucket_example_lifecycle_rule_test.go create mode 100644 rules/azurerm_storage_account_tls_version.go delete mode 100644 rules/google_compute_ssl_policy.go delete mode 100644 rules/google_compute_ssl_policy_test.go delete mode 100644 rules/terraform_backend_type.go delete mode 100644 rules/terraform_backend_type_test.go diff --git a/go.mod b/go.mod index d73954c..452d79f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/terraform-linters/tflint-ruleset-template -go 1.22.2 +go 1.22.5 + +toolchain go1.22.8 require ( github.com/hashicorp/hcl/v2 v2.22.0 @@ -22,6 +24,7 @@ require ( github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/oklog/run v1.0.0 // indirect + github.com/terraform-linters/tflint-ruleset-azurerm v0.27.0 // indirect github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zclconf/go-cty v1.15.0 // indirect diff --git a/go.sum b/go.sum index ca5a5f7..64585e9 100644 --- a/go.sum +++ b/go.sum @@ -47,6 +47,8 @@ github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8 github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/terraform-linters/tflint-plugin-sdk v0.21.0 h1:RoorxuuWh1RuL09PWAmaCKw/hmb9QP5dukGXZiB0fs8= github.com/terraform-linters/tflint-plugin-sdk v0.21.0/go.mod h1:f7ruoYh44RQvnZRxpWhn8JFkpEVlQFT8wC9MhIF0Rp4= +github.com/terraform-linters/tflint-ruleset-azurerm v0.27.0 h1:cpig7LDxfs+1b8aD0qtDfuWbIMIWvnW24BUM55oxjgo= +github.com/terraform-linters/tflint-ruleset-azurerm v0.27.0/go.mod h1:mq+FLUb5gC2omEHpz4lyDxAOInP4YQ8cjdgwisohckU= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= diff --git a/main.go b/main.go index 9c1dfc0..fa1b037 100644 --- a/main.go +++ b/main.go @@ -9,14 +9,11 @@ import ( func main() { plugin.Serve(&plugin.ServeOpts{ RuleSet: &tflint.BuiltinRuleSet{ - Name: "template", + Name: "azurerm-security", Version: "0.1.0", Rules: []tflint.Rule{ - rules.NewAwsInstanceExampleTypeRule(), - rules.NewAwsS3BucketExampleLifecycleRule(), - rules.NewGoogleComputeSSLPolicyRule(), - rules.NewTerraformBackendTypeRule(), + rules.NewAzurermStorageAccountUnsecureTls(), }, }, }) -} +} \ No newline at end of file diff --git a/rules/aws_instance_example_type.go b/rules/aws_instance_example_type.go deleted file mode 100644 index 5290594..0000000 --- a/rules/aws_instance_example_type.go +++ /dev/null @@ -1,75 +0,0 @@ -package rules - -import ( - "fmt" - - "github.com/terraform-linters/tflint-plugin-sdk/hclext" - "github.com/terraform-linters/tflint-plugin-sdk/logger" - "github.com/terraform-linters/tflint-plugin-sdk/tflint" -) - -// AwsInstanceExampleTypeRule checks whether ... -type AwsInstanceExampleTypeRule struct { - tflint.DefaultRule -} - -// NewAwsInstanceExampleTypeRule returns a new rule -func NewAwsInstanceExampleTypeRule() *AwsInstanceExampleTypeRule { - return &AwsInstanceExampleTypeRule{} -} - -// Name returns the rule name -func (r *AwsInstanceExampleTypeRule) Name() string { - return "aws_instance_example_type" -} - -// Enabled returns whether the rule is enabled by default -func (r *AwsInstanceExampleTypeRule) Enabled() bool { - return true -} - -// Severity returns the rule severity -func (r *AwsInstanceExampleTypeRule) Severity() tflint.Severity { - return tflint.ERROR -} - -// Link returns the rule reference link -func (r *AwsInstanceExampleTypeRule) Link() string { - return "" -} - -// Check checks whether ... -func (r *AwsInstanceExampleTypeRule) Check(runner tflint.Runner) error { - // This rule is an example to get a top-level resource attribute. - resources, err := runner.GetResourceContent("aws_instance", &hclext.BodySchema{ - Attributes: []hclext.AttributeSchema{ - {Name: "instance_type"}, - }, - }, nil) - if err != nil { - return err - } - - // Put a log that can be output with `TFLINT_LOG=debug` - logger.Debug(fmt.Sprintf("Get %d instances", len(resources.Blocks))) - - for _, resource := range resources.Blocks { - attribute, exists := resource.Body.Attributes["instance_type"] - if !exists { - continue - } - - err := runner.EvaluateExpr(attribute.Expr, func (instanceType string) error { - return runner.EmitIssue( - r, - fmt.Sprintf("instance type is %s", instanceType), - attribute.Expr.Range(), - ) - }, nil) - if err != nil { - return err - } - } - - return nil -} diff --git a/rules/aws_instance_example_type_test.go b/rules/aws_instance_example_type_test.go deleted file mode 100644 index 279f4e5..0000000 --- a/rules/aws_instance_example_type_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package rules - -import ( - "testing" - - hcl "github.com/hashicorp/hcl/v2" - "github.com/terraform-linters/tflint-plugin-sdk/helper" -) - -func Test_AwsInstanceExampleType(t *testing.T) { - tests := []struct { - Name string - Content string - Expected helper.Issues - }{ - { - Name: "issue found", - Content: ` -resource "aws_instance" "web" { - instance_type = "t2.micro" -}`, - Expected: helper.Issues{ - { - Rule: NewAwsInstanceExampleTypeRule(), - Message: "instance type is t2.micro", - Range: hcl.Range{ - Filename: "resource.tf", - Start: hcl.Pos{Line: 3, Column: 21}, - End: hcl.Pos{Line: 3, Column: 31}, - }, - }, - }, - }, - } - - rule := NewAwsInstanceExampleTypeRule() - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content}) - - if err := rule.Check(runner); err != nil { - t.Fatalf("Unexpected error occurred: %s", err) - } - - helper.AssertIssues(t, test.Expected, runner.Issues) - }) - } -} diff --git a/rules/aws_s3_bucket_example_lifecycle_rule.go b/rules/aws_s3_bucket_example_lifecycle_rule.go deleted file mode 100644 index 87c2db1..0000000 --- a/rules/aws_s3_bucket_example_lifecycle_rule.go +++ /dev/null @@ -1,81 +0,0 @@ -package rules - -import ( - "github.com/terraform-linters/tflint-plugin-sdk/hclext" - "github.com/terraform-linters/tflint-plugin-sdk/tflint" -) - -// AwsS3BucketExampleLifecycleRule checks whether ... -type AwsS3BucketExampleLifecycleRule struct { - tflint.DefaultRule -} - -// NewAwsS3BucketExampleLifecycleRule returns a new rule -func NewAwsS3BucketExampleLifecycleRule() *AwsS3BucketExampleLifecycleRule { - return &AwsS3BucketExampleLifecycleRule{} -} - -// Name returns the rule name -func (r *AwsS3BucketExampleLifecycleRule) Name() string { - return "aws_s3_bucket_example_lifecycle_rule" -} - -// Enabled returns whether the rule is enabled by default -func (r *AwsS3BucketExampleLifecycleRule) Enabled() bool { - return true -} - -// Severity returns the rule severity -func (r *AwsS3BucketExampleLifecycleRule) Severity() tflint.Severity { - return tflint.ERROR -} - -// Link returns the rule reference link -func (r *AwsS3BucketExampleLifecycleRule) Link() string { - return "" -} - -// Check checks whether ... -func (r *AwsS3BucketExampleLifecycleRule) Check(runner tflint.Runner) error { - // This rule is an example to get nested resource attributes. - resources, err := runner.GetResourceContent("aws_s3_bucket", &hclext.BodySchema{ - Blocks: []hclext.BlockSchema{ - { - Type: "lifecycle_rule", - Body: &hclext.BodySchema{ - Attributes: []hclext.AttributeSchema{ - {Name: "enabled"}, - }, - Blocks: []hclext.BlockSchema{ - {Type: "transition"}, - }, - }, - }, - }, - }, nil) - if err != nil { - return err - } - - for _, resource := range resources.Blocks { - for _, rule := range resource.Body.Blocks { - if err := runner.EmitIssue(r, "`lifecycle_rule` block found", rule.DefRange); err != nil { - return err - } - - if attr, exists := rule.Body.Attributes["enabled"]; exists { - if err := runner.EmitIssue(r, "`enabled` attribute found", attr.Expr.Range()); err != nil { - return err - } - } - - for _, transitions := range rule.Body.Blocks { - if err := runner.EmitIssue(r, "`transition` block found", transitions.DefRange); err != nil { - return err - } - } - } - } - - return nil -} diff --git a/rules/aws_s3_bucket_example_lifecycle_rule_test.go b/rules/aws_s3_bucket_example_lifecycle_rule_test.go deleted file mode 100644 index 98d0524..0000000 --- a/rules/aws_s3_bucket_example_lifecycle_rule_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package rules - -import ( - "testing" - - hcl "github.com/hashicorp/hcl/v2" - "github.com/terraform-linters/tflint-plugin-sdk/helper" -) - -func Test_AwsS3BucketExampleLifecycleRule(t *testing.T) { - tests := []struct { - Name string - Content string - Expected helper.Issues - }{ - { - Name: "issue found", - Content: ` -resource "aws_s3_bucket" "bucket" { - lifecycle_rule { - enabled = false - - transition { - days = 30 - storage_class = "STANDARD_IA" - } - } -}`, - Expected: helper.Issues{ - { - Rule: NewAwsS3BucketExampleLifecycleRule(), - Message: "`lifecycle_rule` block found", - Range: hcl.Range{ - Filename: "resource.tf", - Start: hcl.Pos{Line: 3, Column: 3}, - End: hcl.Pos{Line: 3, Column: 17}, - }, - }, - { - Rule: NewAwsS3BucketExampleLifecycleRule(), - Message: "`enabled` attribute found", - Range: hcl.Range{ - Filename: "resource.tf", - Start: hcl.Pos{Line: 4, Column: 15}, - End: hcl.Pos{Line: 4, Column: 20}, - }, - }, - { - Rule: NewAwsS3BucketExampleLifecycleRule(), - Message: "`transition` block found", - Range: hcl.Range{ - Filename: "resource.tf", - Start: hcl.Pos{Line: 6, Column: 5}, - End: hcl.Pos{Line: 6, Column: 15}, - }, - }, - }, - }, - } - - rule := NewAwsS3BucketExampleLifecycleRule() - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content}) - - if err := rule.Check(runner); err != nil { - t.Fatalf("Unexpected error occurred: %s", err) - } - - helper.AssertIssues(t, test.Expected, runner.Issues) - }) - } -} diff --git a/rules/azurerm_storage_account_tls_version.go b/rules/azurerm_storage_account_tls_version.go new file mode 100644 index 0000000..7bfcc17 --- /dev/null +++ b/rules/azurerm_storage_account_tls_version.go @@ -0,0 +1,92 @@ +// This file generated by `tools/apispec-rule-gen/main.go`. DO NOT EDIT + +package rules + +import ( + "fmt" + + "github.com/terraform-linters/tflint-plugin-sdk/hclext" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" + // "github.com/terraform-linters/tflint-ruleset-azurerm/project" +) + +// AzurermStorageAccountUnsecureTls checks the pattern is valid +type AzurermStorageAccountUnsecureTls struct { + tflint.DefaultRule + + resourceType string + attributeName string + enum []string +} + +// NewAzurermStorageAccountUnsecureTls returns new rule with default attributes +func NewAzurermStorageAccountUnsecureTls() *AzurermStorageAccountUnsecureTls { + return &AzurermStorageAccountUnsecureTls{ + resourceType: "azurerm_storage_account", + attributeName: "min_tls_version", + enum: []string{ + "TLS1_2", + "TLS1_3", + }, + } +} + +// Name returns the rule name +func (r *AzurermStorageAccountUnsecureTls) Name() string { + return "azurerm_storage_account_unsecure_tls" +} + +// Enabled returns whether the rule is enabled by default +func (r *AzurermStorageAccountUnsecureTls) Enabled() bool { + return true +} + +// Severity returns the rule severity +func (r *AzurermStorageAccountUnsecureTls) Severity() tflint.Severity { + return tflint.ERROR +} + +// Link returns the rule reference link +func (r *AzurermStorageAccountUnsecureTls) Link() string { + return "" +} + +// Check checks the pattern is valid +func (r *AzurermStorageAccountUnsecureTls) Check(runner tflint.Runner) error { + resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{ + Attributes: []hclext.AttributeSchema{ + {Name: r.attributeName}, + }, + }, nil) + if err != nil { + return err + } + + for _, resource := range resources.Blocks { + attribute, exists := resource.Body.Attributes[r.attributeName] + if !exists { + continue + } + err := runner.EvaluateExpr(attribute.Expr, func (val string) error { + found := false + for _, item := range r.enum { + if item == val { + found = true + } + } + if !found { + runner.EmitIssue( + r, + fmt.Sprintf(`"%s" is an insecure value as min_tls_version`, val), + attribute.Expr.Range(), + ) + } + return nil + }, nil) + if err != nil { + return err + } + } + + return nil +} \ No newline at end of file diff --git a/rules/google_compute_ssl_policy.go b/rules/google_compute_ssl_policy.go deleted file mode 100644 index fd345f9..0000000 --- a/rules/google_compute_ssl_policy.go +++ /dev/null @@ -1,87 +0,0 @@ -package rules - -import ( - "fmt" - - "github.com/terraform-linters/tflint-plugin-sdk/hclext" - "github.com/terraform-linters/tflint-plugin-sdk/tflint" -) - -// GoogleComputeSSLPolicyRule checks whether ... -type GoogleComputeSSLPolicyRule struct { - tflint.DefaultRule -} - -// GoogleComputeSSLPolicyRuleConfig is a config of GoogleComputeSSLPolicyRule -type GoogleComputeSSLPolicyRuleConfig struct { - AllowedVersions []string `hclext:"allowed_versions"` -} - -// NewGoogleComputeSSLPolicyRule returns a new rule -func NewGoogleComputeSSLPolicyRule() *GoogleComputeSSLPolicyRule { - return &GoogleComputeSSLPolicyRule{} -} - -// Name returns the rule name -func (r *GoogleComputeSSLPolicyRule) Name() string { - return "google_compute_ssl_policy" -} - -// Enabled returns whether the rule is enabled by default -func (r *GoogleComputeSSLPolicyRule) Enabled() bool { - // Need to configure `allowed_versions` - return false -} - -// Severity returns the rule severity -func (r *GoogleComputeSSLPolicyRule) Severity() tflint.Severity { - return tflint.WARNING -} - -// Link returns the rule reference link -func (r *GoogleComputeSSLPolicyRule) Link() string { - return "" -} - -// Check checks whether ... -func (r *GoogleComputeSSLPolicyRule) Check(runner tflint.Runner) error { - // This rule is an example to use custom rule config. - config := &GoogleComputeSSLPolicyRuleConfig{} - if err := runner.DecodeRuleConfig(r.Name(), config); err != nil { - return err - } - - resources, err := runner.GetResourceContent("google_compute_ssl_policy", &hclext.BodySchema{ - Attributes: []hclext.AttributeSchema{ - {Name: "min_tls_version"}, - }, - }, nil) - if err != nil { - return err - } - - for _, resource := range resources.Blocks { - attribute, exists := resource.Body.Attributes["min_tls_version"] - if !exists { - continue - } - - err := runner.EvaluateExpr(attribute.Expr, func (version string) error { - for _, allow := range config.AllowedVersions { - if version == allow { - return nil - } - } - return runner.EmitIssue( - r, - fmt.Sprintf(`"%s" is not allowed`, version), - attribute.Expr.Range(), - ) - }, nil) - if err != nil { - return err - } - } - - return nil -} diff --git a/rules/google_compute_ssl_policy_test.go b/rules/google_compute_ssl_policy_test.go deleted file mode 100644 index d5f22b7..0000000 --- a/rules/google_compute_ssl_policy_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package rules - -import ( - "testing" - - hcl "github.com/hashicorp/hcl/v2" - "github.com/terraform-linters/tflint-plugin-sdk/helper" -) - -func Test_GoogleComputeSSLPolicyRule(t *testing.T) { - tests := []struct { - Name string - Content string - Config string - Expected helper.Issues - }{ - { - Name: "issue found", - Content: ` -resource "google_compute_ssl_policy" "allowed" { - min_tls_version = "TLS_1_1" -}`, - Config: ` -rule "google_compute_ssl_policy" { - enabled = true - allowed_versions = ["TLS_1_2"] -}`, - Expected: helper.Issues{ - { - Rule: NewGoogleComputeSSLPolicyRule(), - Message: `"TLS_1_1" is not allowed`, - Range: hcl.Range{ - Filename: "resource.tf", - Start: hcl.Pos{Line: 3, Column: 21}, - End: hcl.Pos{Line: 3, Column: 30}, - }, - }, - }, - }, - { - Name: "issue not found", - Content: ` -resource "google_compute_ssl_policy" "allowed" { - min_tls_version = "TLS_1_1" -}`, - Config: ` -rule "google_compute_ssl_policy" { - enabled = true - allowed_versions = ["TLS_1_1", "TLS_1_2"] -}`, - Expected: helper.Issues{}, - }, - } - - rule := NewGoogleComputeSSLPolicyRule() - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content, ".tflint.hcl": test.Config}) - - if err := rule.Check(runner); err != nil { - t.Fatalf("Unexpected error occurred: %s", err) - } - - helper.AssertIssues(t, test.Expected, runner.Issues) - }) - } -} diff --git a/rules/terraform_backend_type.go b/rules/terraform_backend_type.go deleted file mode 100644 index b7cd682..0000000 --- a/rules/terraform_backend_type.go +++ /dev/null @@ -1,76 +0,0 @@ -package rules - -import ( - "fmt" - - "github.com/terraform-linters/tflint-plugin-sdk/hclext" - "github.com/terraform-linters/tflint-plugin-sdk/tflint" -) - -// TerraformBackendTypeRule checks whether ... -type TerraformBackendTypeRule struct { - tflint.DefaultRule -} - -// NewTerraformBackendTypeRule returns a new rule -func NewTerraformBackendTypeRule() *TerraformBackendTypeRule { - return &TerraformBackendTypeRule{} -} - -// Name returns the rule name -func (r *TerraformBackendTypeRule) Name() string { - return "terraform_backend_type" -} - -// Enabled returns whether the rule is enabled by default -func (r *TerraformBackendTypeRule) Enabled() bool { - return true -} - -// Severity returns the rule severity -func (r *TerraformBackendTypeRule) Severity() tflint.Severity { - return tflint.ERROR -} - -// Link returns the rule reference link -func (r *TerraformBackendTypeRule) Link() string { - return "" -} - -// Check checks whether ... -func (r *TerraformBackendTypeRule) Check(runner tflint.Runner) error { - // This rule is an example to get attributes of blocks other than resources. - content, err := runner.GetModuleContent(&hclext.BodySchema{ - Blocks: []hclext.BlockSchema{ - { - Type: "terraform", - Body: &hclext.BodySchema{ - Blocks: []hclext.BlockSchema{ - { - Type: "backend", - LabelNames: []string{"type"}, - }, - }, - }, - }, - }, - }, nil) - if err != nil { - return err - } - - for _, terraform := range content.Blocks { - for _, backend := range terraform.Body.Blocks { - err := runner.EmitIssue( - r, - fmt.Sprintf("backend type is %s", backend.Labels[0]), - backend.DefRange, - ) - if err != nil { - return err - } - } - } - - return nil -} diff --git a/rules/terraform_backend_type_test.go b/rules/terraform_backend_type_test.go deleted file mode 100644 index d3a23ae..0000000 --- a/rules/terraform_backend_type_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package rules - -import ( - "testing" - - hcl "github.com/hashicorp/hcl/v2" - "github.com/terraform-linters/tflint-plugin-sdk/helper" -) - -func Test_TerraformBackendType(t *testing.T) { - tests := []struct { - Name string - Content string - Expected helper.Issues - }{ - { - Name: "issue found", - Content: ` -terraform { - backend "s3" { - bucket = "mybucket" - key = "path/to/my/key" - region = "us-east-1" - } -}`, - Expected: helper.Issues{ - { - Rule: NewTerraformBackendTypeRule(), - Message: "backend type is s3", - Range: hcl.Range{ - Filename: "resource.tf", - Start: hcl.Pos{Line: 3, Column: 3}, - End: hcl.Pos{Line: 3, Column: 15}, - }, - }, - }, - }, - } - - rule := NewTerraformBackendTypeRule() - - for _, test := range tests { - t.Run(test.Name, func(t *testing.T) { - runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content}) - - if err := rule.Check(runner); err != nil { - t.Fatalf("Unexpected error occurred: %s", err) - } - - helper.AssertIssues(t, test.Expected, runner.Issues) - }) - } -}