From 6c669fdae69b7d99536be3e440ffe4006b6cb113 Mon Sep 17 00:00:00 2001 From: Preben Huybrechts Date: Thu, 31 Oct 2024 14:36:37 +0100 Subject: [PATCH] new rules --- README.md | 2 + main.go | 2 + rules/azurerm_windows_web_app_ftps_state.go | 87 +++++++++++++++++++ ...azurerm_windows_web_app_ftps_state_test.go | 75 ++++++++++++++++ ...erm_windows_web_app_minimum_tls_version.go | 87 +++++++++++++++++++ ...indows_web_app_minimum_tls_version_test.go | 74 ++++++++++++++++ 6 files changed, 327 insertions(+) create mode 100644 rules/azurerm_windows_web_app_ftps_state.go create mode 100644 rules/azurerm_windows_web_app_ftps_state_test.go create mode 100644 rules/azurerm_windows_web_app_minimum_tls_version.go create mode 100644 rules/azurerm_windows_web_app_minimum_tls_version_test.go diff --git a/README.md b/README.md index 8dc4170..ec6af30 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ plugin "template" { |azurerm_linux_web_app_minimum_tls_version|Enforce TLS 1.2 on linux web apps |ERROR|✔|| |azurerm_mssql_database_transparent_data_encryption_enabled|Enforce transparant data encryption|ERROR|✔|| |azurerm_storage_account_tls_version|Enforce TLS 1.2 on storage accounts |ERROR|✔|| +|azurerm_windows_web_app_ftps_state|Disable sftp to a windows web app |ERROR|✔|| +|azurerm_windows_web_app_minimum_tls_version|Enforce TLS 1.2 on windows web apps |ERROR|✔|| ## Building the plugin diff --git a/main.go b/main.go index 3aba763..d7eb31e 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,8 @@ func main() { rules.NewAzurermLinuxWebAppMinimumTlsVersion(), rules.NewAzurermMssqlDatabaseEncryption(), rules.NewAzurermStorageAccountUnsecureTls(), + rules.NewAzurermWindowsWebAppFtpsState(), + rules.NewAzurermWindowsWebAppMinimumTlsVersion(), }, }, }) diff --git a/rules/azurerm_windows_web_app_ftps_state.go b/rules/azurerm_windows_web_app_ftps_state.go new file mode 100644 index 0000000..c5dc7a6 --- /dev/null +++ b/rules/azurerm_windows_web_app_ftps_state.go @@ -0,0 +1,87 @@ +package rules + +import ( + "fmt" + + "github.com/terraform-linters/tflint-plugin-sdk/hclext" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" +) + +// AzurermWindowsWebAppFtpsState checks if ftps_state is disabled +type AzurermWindowsWebAppFtpsState struct { + tflint.DefaultRule + + resourceType string + attributeName string + expectedValue string +} + +// NewAzurermWindowsWebAppFtpsState creates a new rule instance +func NewAzurermWindowsWebAppFtpsState() *AzurermWindowsWebAppFtpsState { + return &AzurermWindowsWebAppFtpsState{ + resourceType: "azurerm_windows_web_app", + attributeName: "ftps_state", + expectedValue: "Disabled", + } +} + +// Name returns the rule name +func (r *AzurermWindowsWebAppFtpsState) Name() string { + return "azurerm_windows_web_app_ftps_state" +} + +// Enabled returns whether the rule is enabled by default +func (r *AzurermWindowsWebAppFtpsState) Enabled() bool { + return true +} + +// Severity returns the rule severity +func (r *AzurermWindowsWebAppFtpsState) Severity() tflint.Severity { + return tflint.ERROR +} + +// Link returns the rule reference link +func (r *AzurermWindowsWebAppFtpsState) Link() string { + return "" +} + +// Check verifies that ftps_state is set to "Disabled" +func (r *AzurermWindowsWebAppFtpsState) 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 { + runner.EmitIssue( + r, + "ftps_state should be set to Disabled", + resource.DefRange, + ) + continue + } + + err := runner.EvaluateExpr(attribute.Expr, func(val string) error { + if val != r.expectedValue { + runner.EmitIssue( + r, + fmt.Sprintf("ftps_state is set to %q, should be Disabled", val), + attribute.Expr.Range(), + ) + } + return nil + }, nil) + + if err != nil { + return err + } + } + + return nil +} \ No newline at end of file diff --git a/rules/azurerm_windows_web_app_ftps_state_test.go b/rules/azurerm_windows_web_app_ftps_state_test.go new file mode 100644 index 0000000..9f3710a --- /dev/null +++ b/rules/azurerm_windows_web_app_ftps_state_test.go @@ -0,0 +1,75 @@ +package rules + +import ( + "testing" + + hcl "github.com/hashicorp/hcl/v2" + "github.com/terraform-linters/tflint-plugin-sdk/helper" +) + +func Test_AzurermWindowsWebAppFtpsState(t *testing.T) { + tests := []struct { + Name string + Content string + Expected helper.Issues + }{ + { + Name: "FTPS enabled", + Content: ` +resource "azurerm_windows_web_app" "example" { + ftps_state = "Enabled" +}`, + Expected: helper.Issues{ + { + Rule: NewAzurermWindowsWebAppFtpsState(), + Message: `ftps_state is set to "Enabled", should be Disabled`, + Range: hcl.Range{ + Filename: "resource.tf", + Start: hcl.Pos{Line: 3, Column: 18}, + End: hcl.Pos{Line: 3, Column: 27}, + }, + }, + }, + }, + { + Name: "FTPS state missing", + Content: ` +resource "azurerm_windows_web_app" "example" { +}`, + Expected: helper.Issues{ + { + Rule: NewAzurermWindowsWebAppFtpsState(), + Message: `ftps_state should be set to Disabled`, + Range: hcl.Range{ + Filename: "resource.tf", + Start: hcl.Pos{Line: 2, Column: 1}, + End: hcl.Pos{Line: 2, Column: 45}, + }, + }, + }, + }, + { + Name: "FTPS disabled", + Content: ` +resource "azurerm_windows_web_app" "example" { + ftps_state = "Disabled" +}`, + Expected: helper.Issues{}, + }, + } + + rule := NewAzurermWindowsWebAppFtpsState() + + 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_windows_web_app_minimum_tls_version.go b/rules/azurerm_windows_web_app_minimum_tls_version.go new file mode 100644 index 0000000..dd1f1ec --- /dev/null +++ b/rules/azurerm_windows_web_app_minimum_tls_version.go @@ -0,0 +1,87 @@ +package rules + +import ( + "fmt" + + "github.com/terraform-linters/tflint-plugin-sdk/hclext" + "github.com/terraform-linters/tflint-plugin-sdk/tflint" +) + +// AzurermWindowsWebAppMinimumTlsVersion checks that minimum_tls_version is set to at least "1.2" +type AzurermWindowsWebAppMinimumTlsVersion struct { + tflint.DefaultRule + + resourceType string + attributeName string + version string +} + +// NewAzurermWindowsWebAppMinimumTlsVersion returns a new rule instance +func NewAzurermWindowsWebAppMinimumTlsVersion() *AzurermWindowsWebAppMinimumTlsVersion { + return &AzurermWindowsWebAppMinimumTlsVersion{ + resourceType: "azurerm_windows_web_app", + attributeName: "minimum_tls_version", + version: "1.2", + } +} + +// Name returns the rule name +func (r *AzurermWindowsWebAppMinimumTlsVersion) Name() string { + return "azurerm_windows_web_app_minimum_tls_version" +} + +// Enabled returns whether the rule is enabled by default +func (r *AzurermWindowsWebAppMinimumTlsVersion) Enabled() bool { + return true +} + +// Severity returns the rule severity +func (r *AzurermWindowsWebAppMinimumTlsVersion) Severity() tflint.Severity { + return tflint.ERROR +} + +// Link returns the rule reference link +func (r *AzurermWindowsWebAppMinimumTlsVersion) Link() string { + return "" +} + +// Check verifies that minimum_tls_version is at least "1.2" +func (r *AzurermWindowsWebAppMinimumTlsVersion) 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 { + // Emit issue if minimum_tls_version attribute is missing + runner.EmitIssue( + r, + fmt.Sprintf("%s is missing, should be set to %s or higher", r.attributeName, r.version), + resource.DefRange, + ) + continue + } + + err := runner.EvaluateExpr(attribute.Expr, func(val string) error { + if val != r.version { + runner.EmitIssue( + r, + fmt.Sprintf("%s is set to %s, should be %s or higher", r.attributeName, val, r.version), + attribute.Expr.Range(), + ) + } + return nil + }, nil) + if err != nil { + return err + } + } + + return nil +} diff --git a/rules/azurerm_windows_web_app_minimum_tls_version_test.go b/rules/azurerm_windows_web_app_minimum_tls_version_test.go new file mode 100644 index 0000000..f3461fa --- /dev/null +++ b/rules/azurerm_windows_web_app_minimum_tls_version_test.go @@ -0,0 +1,74 @@ +package rules + +import ( + "testing" + + hcl "github.com/hashicorp/hcl/v2" + "github.com/terraform-linters/tflint-plugin-sdk/helper" +) + +func Test_AzurermWindowsWebAppMinimumTlsVersion(t *testing.T) { + tests := []struct { + Name string + Content string + Expected helper.Issues + }{ + { + Name: "minimum_tls_version below 1.2", + Content: ` +resource "azurerm_windows_web_app" "example" { + minimum_tls_version = "1.0" +}`, + Expected: helper.Issues{ + { + Rule: NewAzurermWindowsWebAppMinimumTlsVersion(), + Message: "minimum_tls_version is set to 1.0, should be 1.2 or higher", + Range: hcl.Range{ + Filename: "resource.tf", + Start: hcl.Pos{Line: 3, Column: 27}, // Adjusted to match the actual position of "1.0" + End: hcl.Pos{Line: 3, Column: 32}, // Adjusted to match the end position after "1.0" + }, + }, + }, + }, + { + Name: "minimum_tls_version set to 1.2", + Content: ` +resource "azurerm_windows_web_app" "example" { + minimum_tls_version = "1.2" +}`, + Expected: helper.Issues{}, + }, + { + Name: "minimum_tls_version attribute missing", + Content: ` +resource "azurerm_windows_web_app" "example" { +}`, + Expected: helper.Issues{ + { + Rule: NewAzurermWindowsWebAppMinimumTlsVersion(), + Message: "minimum_tls_version is missing, should be set to 1.2 or higher", + Range: hcl.Range{ + Filename: "resource.tf", + Start: hcl.Pos{Line: 2, Column: 1}, // Start at the beginning of the resource block + End: hcl.Pos{Line: 2, Column: 45}, // End at the end of the resource block (adjusted) + }, + }, + }, + }, + } + + rule := NewAzurermWindowsWebAppMinimumTlsVersion() + + 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) + }) + } +}