Repository: aquasecurity/tfsec
Pull request #1030 (2021-08-16 15:00:37)

2146 app service checks
- Fix typo in name
- adding app service checks



Patch:
diff --git a/cmd/tfsec-skeleton/requirements/comparison.go b/cmd/tfsec-skeleton/requirements/comparison.go
index 4335f0630..8d9409f40 100644
--- a/cmd/tfsec-skeleton/requirements/comparison.go
+++ b/cmd/tfsec-skeleton/requirements/comparison.go
@@ -18,8 +18,8 @@ const (
 	ComparisonNotDefined         Comparison = "notdefined"
 	ComparisonIsEmpty            Comparison = "empty"
 	ComparisonNotEmpty           Comparison = "notempty"
-	ComparisonIsTrue             Comparison = "istrue"
-	ComparisonIsFalse            Comparison = "isfalse"
+	ComparisonIsTrue             Comparison = "true"
+	ComparisonIsFalse            Comparison = "false"
 )
 
 func (c Comparison) Reverse() Comparison {
diff --git a/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule.go b/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule.go
new file mode 100644
index 000000000..2d3ba421d
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule.go
@@ -0,0 +1,65 @@
+package appservice
+
+// ATTENTION!
+// This rule was autogenerated!
+// Before making changes, consider updating the generator.
+
+import (
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/pkg/provider"
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/rule"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Provider:  provider.AzureProvider,
+		Service:   "appservice",
+		ShortCode: "account-identity-registered",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Web App has registration with AD enabled",
+			Explanation: `Registering the identity used by an App with AD allows it to interact with other services without using username and password`,
+			Impact:      "Interaction between services can't easily be achieved without username/password",
+			Resolution:  "Register the app identity with AD",
+			BadExample: []string{`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+}
+`},
+			GoodExample: []string{`
+resource "azurerm_app_service" "good_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+
+  identity {
+    type = "UserAssigned"
+    identity_ids = "webapp1"
+  }
+}
+`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#identity",
+			},
+		},
+		RequiredTypes: []string{
+			"resource",
+		},
+		RequiredLabels: []string{
+			"azurerm_app_service",
+		},
+		DefaultSeverity: severity.Low,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, module block.Module) {
+			if identityAttr := resourceBlock.GetBlock("identity"); identityAttr.IsNil() { // alert on use of default value
+				set.AddResult().
+					WithDescription("Resource '%s' does not set identity", resourceBlock.FullName())
+			}
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go b/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go
new file mode 100644
index 000000000..4f41452f0
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go
@@ -0,0 +1,68 @@
+package appservice
+
+// ATTENTION!
+// This rule was autogenerated!
+// Before making changes, consider updating the generator.
+
+import (
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/pkg/provider"
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/rule"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Provider:  provider.AzureProvider,
+		Service:   "appservice",
+		ShortCode: "authentication-enabled",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "App Service authentication is activated",
+			Explanation: `Enabling authentication ensures that all communications in the application are authenticated. The auth_settings block needs to be filled out with the appropriate auth backend settings`,
+			Impact:      "Anonymous HTTP requests will be accepted",
+			Resolution:  "Enable authentication to prevent anonymous request being accepted",
+			BadExample: []string{`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+}
+`},
+			GoodExample: []string{`
+resource "azurerm_app_service" "good_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+
+  auth_settings {
+    enabled = true
+  }
+}
+`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#enabled",
+			},
+		},
+		RequiredTypes: []string{
+			"resource",
+		},
+		RequiredLabels: []string{
+			"azurerm_app_service",
+		},
+		DefaultSeverity: severity.Medium,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, module block.Module) {
+			if enabledAttr := resourceBlock.GetBlock("auth_settings").GetAttribute("enabled"); enabledAttr.IsNil() { // alert on use of default value
+				set.AddResult().
+					WithDescription("Resource '%s' uses default value for auth_settings.enabled", resourceBlock.FullName())
+			} else if enabledAttr.IsFalse() {
+				set.AddResult().
+					WithDescription("Resource '%s' has attribute auth_settings.enabled that is false", resourceBlock.FullName()).
+					WithAttribute(enabledAttr)
+			}
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go b/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go
new file mode 100644
index 000000000..7727b4bbc
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go
@@ -0,0 +1,79 @@
+package appservice
+
+// ATTENTION!
+// This rule was autogenerated!
+// Before making changes, consider updating the generator.
+
+import (
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/pkg/provider"
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/rule"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Provider:  provider.AzureProvider,
+		Service:   "appservice",
+		ShortCode: "enable-http2",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Web App uses the latest HTTP version",
+			Explanation: `Use the latest version of HTTP to ensure you are benefiting from security fixes`,
+			Impact:      "Outdated versions of HTTP has security vulnerabilities",
+			Resolution:  "Use the latest version of HTTP",
+			BadExample: []string{`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+}
+`,
+				`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+  site_config {
+	  http2_enabled = false
+  }
+}
+`},
+			GoodExample: []string{`
+resource "azurerm_app_service" "good_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+
+  site_config {
+	  http2_enabled = true
+  }
+}
+`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#http2_enabled",
+			},
+		},
+		RequiredTypes: []string{
+			"resource",
+		},
+		RequiredLabels: []string{
+			"azurerm_app_service",
+		},
+		DefaultSeverity: severity.Low,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, module block.Module) {
+			if http2EnabledAttr := resourceBlock.GetBlock("site_config").GetAttribute("http2_enabled"); http2EnabledAttr.IsNil() { // alert on use of default value
+				set.AddResult().
+					WithDescription("Resource '%s' uses default value for site_config.http2_enabled", resourceBlock.FullName())
+			} else if http2EnabledAttr.IsFalse() {
+				set.AddResult().
+					WithDescription("Resource '%s' has attribute site_config.http2_enabled that is false", resourceBlock.FullName()).
+					WithAttribute(http2EnabledAttr)
+			}
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule.go b/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule.go
new file mode 100644
index 000000000..d968164ae
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule.go
@@ -0,0 +1,75 @@
+package appservice
+
+// ATTENTION!
+// This rule was autogenerated!
+// Before making changes, consider updating the generator.
+
+import (
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/pkg/provider"
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/rule"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Provider:  provider.AzureProvider,
+		Service:   "appservice",
+		ShortCode: "require-client-cert",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Web App accepts incoming client certificate",
+			Explanation: `The TLS mutual authentication technique in enterprise environments ensures the authenticity of clients to the server. If incoming client certificates are enabled only an authenticated client with valid certificates can access the app.`,
+			Impact:      "Mutual TLS is not being used",
+			Resolution:  "Enable incoming certificates for clients",
+			BadExample: []string{`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+}
+`,
+				`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+  client_cert_enabled = false
+}
+`,
+			},
+			GoodExample: []string{`
+resource "azurerm_app_service" "good_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+  client_cert_enabled = true
+}
+`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#client_cert_enabled",
+			},
+		},
+		RequiredTypes: []string{
+			"resource",
+		},
+		RequiredLabels: []string{
+			"azurerm_app_service",
+		},
+		DefaultSeverity: severity.Low,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, module block.Module) {
+			if clientCertEnabledAttr := resourceBlock.GetAttribute("client_cert_enabled"); clientCertEnabledAttr.IsNil() { // alert on use of default value
+				set.AddResult().
+					WithDescription("Resource '%s' uses default value for client_cert_enabled", resourceBlock.FullName())
+			} else if clientCertEnabledAttr.IsFalse() {
+				set.AddResult().
+					WithDescription("Resource '%s' has attribute client_cert_enabled that is false", resourceBlock.FullName()).
+					WithAttribute(clientCertEnabledAttr)
+			}
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/use_secure_tls_policy_rule.go b/internal/app/tfsec/rules/azure/appservice/use_secure_tls_policy_rule.go
new file mode 100644
index 000000000..23b3fdb37
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/use_secure_tls_policy_rule.go
@@ -0,0 +1,69 @@
+package appservice
+
+// ATTENTION!
+// This rule was autogenerated!
+// Before making changes, consider updating the generator.
+
+import (
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/pkg/provider"
+	"github.com/aquasecurity/tfsec/pkg/result"
+	"github.com/aquasecurity/tfsec/pkg/rule"
+	"github.com/aquasecurity/tfsec/pkg/severity"
+)
+
+func init() {
+	scanner.RegisterCheckRule(rule.Rule{
+		Provider:  provider.AzureProvider,
+		Service:   "appservice",
+		ShortCode: "use-secure-tls-policy",
+		Documentation: rule.RuleDocumentation{
+			Summary:     "Web App uses latest TLS version",
+			Explanation: `Use a more recent TLS/SSL policy for the App Service`,
+			Impact:      "The minimum TLS version for apps should be TLS1_2",
+			Resolution:  "The TLS version being outdated and has known vulnerabilities",
+			BadExample: []string{`
+resource "azurerm_app_service" "bad_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+
+  site_config {
+	  min_tls_version = "1.0"
+  }
+}
+`},
+			GoodExample: []string{`
+resource "azurerm_app_service" "good_example" {
+  name                = "example-app-service"
+  location            = azurerm_resource_group.example.location
+  resource_group_name = azurerm_resource_group.example.name
+  app_service_plan_id = azurerm_app_service_plan.example.id
+}
+`},
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/app_service#min_tls_version",
+			},
+		},
+		RequiredTypes: []string{
+			"resource",
+		},
+		RequiredLabels: []string{
+			"azurerm_app_service",
+		},
+		DefaultSeverity: severity.High,
+		CheckFunc: func(set result.Set, resourceBlock block.Block, module block.Module) {
+			if resourceBlock.MissingChild("site_config") {
+				return
+			}
+
+			if minTlsVersionAttr := resourceBlock.GetBlock("site_config").GetAttribute("min_tls_version"); minTlsVersionAttr.IsNotNil() && minTlsVersionAttr.NotEqual("1.2") {
+				set.AddResult().
+					WithDescription("Resource '%s' does not have site_config.min_tls_version set to 1.2", resourceBlock.FullName()).
+					WithAttribute(minTlsVersionAttr)
+			}
+		},
+	})
+}
diff --git a/internal/app/tfsec/rules/azure/database/postgres_configration_log_checkpoints_rule.go b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_checkpoints_rule.go
similarity index 98%
rename from internal/app/tfsec/rules/azure/database/postgres_configration_log_checkpoints_rule.go
rename to internal/app/tfsec/rules/azure/database/postgres_configuration_log_checkpoints_rule.go
index 213a185ec..b0b1e39f0 100644
--- a/internal/app/tfsec/rules/azure/database/postgres_configration_log_checkpoints_rule.go
+++ b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_checkpoints_rule.go
@@ -18,7 +18,7 @@ func init() {
 	scanner.RegisterCheckRule(rule.Rule{
 		Provider:  provider.AzureProvider,
 		Service:   "database",
-		ShortCode: "postgres-configration-log-checkpoints",
+		ShortCode: "postgres-configuration-log-checkpoints",
 		Documentation: rule.RuleDocumentation{
 			Summary:     "Ensure server parameter 'log_checkpoints' is set to 'ON' for PostgreSQL Database Server",
 			Explanation: `Postgresql can generate logs for checkpoints to improve visibility for audit and configuration issue resolution.`,
diff --git a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connection_throttling_rule.go b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connection_throttling_rule.go
similarity index 98%
rename from internal/app/tfsec/rules/azure/database/postgres_configration_log_connection_throttling_rule.go
rename to internal/app/tfsec/rules/azure/database/postgres_configuration_log_connection_throttling_rule.go
index d3a513ac5..886ec6df1 100644
--- a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connection_throttling_rule.go
+++ b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connection_throttling_rule.go
@@ -18,7 +18,7 @@ func init() {
 	scanner.RegisterCheckRule(rule.Rule{
 		Provider:  provider.AzureProvider,
 		Service:   "database",
-		ShortCode: "postgres-configration-log-connection-throttling",
+		ShortCode: "postgres-configuration-log-connection-throttling",
 		Documentation: rule.RuleDocumentation{
 			Summary:     "Ensure server parameter 'connection_throttling' is set to 'ON' for PostgreSQL Database Server",
 			Explanation: `Postgresql can generate logs for connection throttling to improve visibility for audit and configuration issue resolution.`,
diff --git a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connections_rule.go b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connections_rule.go
similarity index 98%
rename from internal/app/tfsec/rules/azure/database/postgres_configration_log_connections_rule.go
rename to internal/app/tfsec/rules/azure/database/postgres_configuration_log_connections_rule.go
index 11a04ffcd..43a244654 100644
--- a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connections_rule.go
+++ b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connections_rule.go
@@ -18,7 +18,7 @@ func init() {
 	scanner.RegisterCheckRule(rule.Rule{
 		Provider:  provider.AzureProvider,
 		Service:   "database",
-		ShortCode: "postgres-configration-log-connections",
+		ShortCode: "postgres-configuration-log-connections",
 		Documentation: rule.RuleDocumentation{
 			Summary:     "Ensure server parameter 'log_connections' is set to 'ON' for PostgreSQL Database Server",
 			Explanation: `Postgresql can generate logs for successful connections to improve visibility for audit and configuration issue resolution.`,


Test patch:
diff --git a/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule_test.go b/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule_test.go
new file mode 100644
index 000000000..e725b3c69
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule_test.go
@@ -0,0 +1,53 @@
+package appservice
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_AzureAccountIdentityRegistered_FailureExamples(t *testing.T) {
+	expectedCode := "azure-appservice-account-identity-registered"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, badExample := range rule.Documentation.BadExample {
+		t.Logf("Running bad example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(badExample) == "" {
+			t.Fatalf("bad example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, rule.ID(), "", results)
+	}
+}
+
+func Test_AzureAccountIdentityRegistered_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-appservice-account-identity-registered"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, example := range rule.Documentation.GoodExample {
+		t.Logf("Running good example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(example) == "" {
+			t.Fatalf("good example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", rule.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule_test.go b/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule_test.go
new file mode 100644
index 000000000..0882b705c
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule_test.go
@@ -0,0 +1,53 @@
+package appservice
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_AzureAuthenticationEnabled_FailureExamples(t *testing.T) {
+	expectedCode := "azure-appservice-authentication-enabled"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, badExample := range rule.Documentation.BadExample {
+		t.Logf("Running bad example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(badExample) == "" {
+			t.Fatalf("bad example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, rule.ID(), "", results)
+	}
+}
+
+func Test_AzureAuthenticationEnabled_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-appservice-authentication-enabled"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, example := range rule.Documentation.GoodExample {
+		t.Logf("Running good example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(example) == "" {
+			t.Fatalf("good example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", rule.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/enable_http2_rule_test.go b/internal/app/tfsec/rules/azure/appservice/enable_http2_rule_test.go
new file mode 100644
index 000000000..b884f32e5
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/enable_http2_rule_test.go
@@ -0,0 +1,53 @@
+package appservice
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_AzureEnableHttp2_FailureExamples(t *testing.T) {
+	expectedCode := "azure-appservice-enable-http2"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, badExample := range rule.Documentation.BadExample {
+		t.Logf("Running bad example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(badExample) == "" {
+			t.Fatalf("bad example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, rule.ID(), "", results)
+	}
+}
+
+func Test_AzureEnableHttp2_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-appservice-enable-http2"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, example := range rule.Documentation.GoodExample {
+		t.Logf("Running good example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(example) == "" {
+			t.Fatalf("good example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", rule.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule_test.go b/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule_test.go
new file mode 100644
index 000000000..e7e4836ef
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule_test.go
@@ -0,0 +1,53 @@
+package appservice
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_AzureRequireClientCert_FailureExamples(t *testing.T) {
+	expectedCode := "azure-appservice-require-client-cert"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, badExample := range rule.Documentation.BadExample {
+		t.Logf("Running bad example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(badExample) == "" {
+			t.Fatalf("bad example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, rule.ID(), "", results)
+	}
+}
+
+func Test_AzureRequireClientCert_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-appservice-require-client-cert"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, example := range rule.Documentation.GoodExample {
+		t.Logf("Running good example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(example) == "" {
+			t.Fatalf("good example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", rule.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/azure/appservice/use_secure_tls_policy_rule_test.go b/internal/app/tfsec/rules/azure/appservice/use_secure_tls_policy_rule_test.go
new file mode 100644
index 000000000..80fce7e71
--- /dev/null
+++ b/internal/app/tfsec/rules/azure/appservice/use_secure_tls_policy_rule_test.go
@@ -0,0 +1,53 @@
+package appservice
+
+import (
+	"strings"
+	"testing"
+
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
+	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
+)
+
+func Test_AzureUseSecureTlsPolicy_FailureExamples(t *testing.T) {
+	expectedCode := "azure-appservice-use-secure-tls-policy"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, badExample := range rule.Documentation.BadExample {
+		t.Logf("Running bad example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(badExample) == "" {
+			t.Fatalf("bad example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (bad) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(badExample, t)
+		testutil.AssertCheckCode(t, rule.ID(), "", results)
+	}
+}
+
+func Test_AzureUseSecureTlsPolicy_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-appservice-use-secure-tls-policy"
+
+	rule, err := scanner.GetRuleById(expectedCode)
+	if err != nil {
+		t.Fatalf("Rule not found: %s", expectedCode)
+	}
+	for i, example := range rule.Documentation.GoodExample {
+		t.Logf("Running good example for '%s' #%d", expectedCode, i+1)
+		if strings.TrimSpace(example) == "" {
+			t.Fatalf("good example code not provided for %s", rule.ID())
+		}
+		defer func() {
+			if err := recover(); err != nil {
+				t.Fatalf("Scan (good) failed: %s", err)
+			}
+		}()
+		results := testutil.ScanHCL(example, t)
+		testutil.AssertCheckCode(t, "", rule.ID(), results)
+	}
+}
diff --git a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connections_rule_test.go b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_checkpoints_rule_test.go
similarity index 80%
rename from internal/app/tfsec/rules/azure/database/postgres_configration_log_connections_rule_test.go
rename to internal/app/tfsec/rules/azure/database/postgres_configuration_log_checkpoints_rule_test.go
index 76d18a9df..d935bf78c 100644
--- a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connections_rule_test.go
+++ b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_checkpoints_rule_test.go
@@ -8,8 +8,8 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
 )
 
-func Test_AzurePostgresConfigrationLogConnections_FailureExamples(t *testing.T) {
-	expectedCode := "azure-database-postgres-configration-log-connections"
+func Test_AzurePostgresConfigurationLogCheckpoints_FailureExamples(t *testing.T) {
+	expectedCode := "azure-database-postgres-configuration-log-checkpoints"
 
 	rule, err := scanner.GetRuleById(expectedCode)
 	if err != nil {
@@ -30,8 +30,8 @@ func Test_AzurePostgresConfigrationLogConnections_FailureExamples(t *testing.T)
 	}
 }
 
-func Test_AzurePostgresConfigrationLogConnections_SuccessExamples(t *testing.T) {
-	expectedCode := "azure-database-postgres-configration-log-connections"
+func Test_AzurePostgresConfigurationLogCheckpoints_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-database-postgres-configuration-log-checkpoints"
 
 	rule, err := scanner.GetRuleById(expectedCode)
 	if err != nil {
diff --git a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connection_throttling_rule_test.go b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connection_throttling_rule_test.go
similarity index 78%
rename from internal/app/tfsec/rules/azure/database/postgres_configration_log_connection_throttling_rule_test.go
rename to internal/app/tfsec/rules/azure/database/postgres_configuration_log_connection_throttling_rule_test.go
index 53e0f4685..7c477358f 100644
--- a/internal/app/tfsec/rules/azure/database/postgres_configration_log_connection_throttling_rule_test.go
+++ b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connection_throttling_rule_test.go
@@ -8,8 +8,8 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
 )
 
-func Test_AzurePostgresConfigrationLogConnectionThrottling_FailureExamples(t *testing.T) {
-	expectedCode := "azure-database-postgres-configration-log-connection-throttling"
+func Test_AzurePostgresConfigurationLogConnectionThrottling_FailureExamples(t *testing.T) {
+	expectedCode := "azure-database-postgres-configuration-log-connection-throttling"
 
 	rule, err := scanner.GetRuleById(expectedCode)
 	if err != nil {
@@ -30,8 +30,8 @@ func Test_AzurePostgresConfigrationLogConnectionThrottling_FailureExamples(t *te
 	}
 }
 
-func Test_AzurePostgresConfigrationLogConnectionThrottling_SuccessExamples(t *testing.T) {
-	expectedCode := "azure-database-postgres-configration-log-connection-throttling"
+func Test_AzurePostgresConfigurationLogConnectionThrottling_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-database-postgres-configuration-log-connection-throttling"
 
 	rule, err := scanner.GetRuleById(expectedCode)
 	if err != nil {
diff --git a/internal/app/tfsec/rules/azure/database/postgres_configration_log_checkpoints_rule_test.go b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connections_rule_test.go
similarity index 80%
rename from internal/app/tfsec/rules/azure/database/postgres_configration_log_checkpoints_rule_test.go
rename to internal/app/tfsec/rules/azure/database/postgres_configuration_log_connections_rule_test.go
index a9f69c116..471bc33d1 100644
--- a/internal/app/tfsec/rules/azure/database/postgres_configration_log_checkpoints_rule_test.go
+++ b/internal/app/tfsec/rules/azure/database/postgres_configuration_log_connections_rule_test.go
@@ -8,8 +8,8 @@ import (
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil"
 )
 
-func Test_AzurePostgresConfigrationLogCheckpoints_FailureExamples(t *testing.T) {
-	expectedCode := "azure-database-postgres-configration-log-checkpoints"
+func Test_AzurePostgresConfigurationLogConnections_FailureExamples(t *testing.T) {
+	expectedCode := "azure-database-postgres-configuration-log-connections"
 
 	rule, err := scanner.GetRuleById(expectedCode)
 	if err != nil {
@@ -30,8 +30,8 @@ func Test_AzurePostgresConfigrationLogCheckpoints_FailureExamples(t *testing.T)
 	}
 }
 
-func Test_AzurePostgresConfigrationLogCheckpoints_SuccessExamples(t *testing.T) {
-	expectedCode := "azure-database-postgres-configration-log-checkpoints"
+func Test_AzurePostgresConfigurationLogConnections_SuccessExamples(t *testing.T) {
+	expectedCode := "azure-database-postgres-configuration-log-connections"
 
 	rule, err := scanner.GetRuleById(expectedCode)
 	if err != nil {