Repository: aquasecurity/tfsec
Pull request #1234 (2022-01-01 16:58:33)

Azure compute - adapt to use defsec
Write the adapters for the virtual machines and the managed disks

According to the Terraform docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_machine#custom_data
 the `custom_data` attribute is part of the `os_profile` block. Update examples and tests accordingly. 

Update examples and tests to include either `os_profile_linux_config` or `os_profile_windows_config` block. One of them is always required by Terraform depending on the os and as such is used by the adapter to classify the virtual machine by os.

Closes: https://github.com/aquasecurity/tfsec/issues/1233


Patch:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 105dbf262..a47c4668a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,7 +42,7 @@ Find your new check and the associated test in one of the subfolders of `interna
 
 Here's an example:
 
-You need to tell the scanner about your check; this is done by calling an init() function with the following code:
+You need to tell the scanner about your check; this is done by calling an `init()` function with the following code:
 
 ```go
 func init() {
@@ -68,27 +68,11 @@ hackable = false
 		RequiredTypes:  []string{"resource"},
 		// the type of resource(s) you want to target
 		RequiredLabels: []string{"aws_gibson"},
-		// the actual logic for your check
-		CheckTerraform: func(block block.Block, module block.Module) (results rules.Results){
-			// TODO: add check logic here
-			return results
-		},
 	})
 }
 ```
 
-Now all that's left is writing the logic itself. You'll likely find it useful here to learn from preexisting check code, but the logic is usually fairly minimal. Here's a basic example:
-
-```go
-...
-
-		CheckTerraform: func(block block.Block, module block.Module) (results rules.Results){
-			if attr := block.GetAttribute("hackable"); attr.IsTrue() {
-				results.Add("The Gibson '%s' is configured to be hackable.", attr)
-			}
-		},
-...
-```
+Now all that's left is writing the logic itself. This has been moved to [defsec](https://github.com/aquasecurity/defsec). You need to make sure that there's an adapter for the resource. You can see [aws/ec2/adapter.go](https://github.com/aquasecurity/tfsec/blob/master/internal/app/tfsec/adapter/aws/ec2/adapt.go) for an example.
 
 You can see a good example of a real check file [here](https://github.com/aquasecurity/tfsec/blob/master/internal/app/tfsec/rules/aws/vpc/no_public_egress_sg_rule.go).
 This check also provides [tests](https://github.com/aquasecurity/tfsec/blob/master/internal/app/tfsec/rules/aws/vpc/no_public_egress_sg_rule_test.go) and uses provided data checks like `cidr.IsAttributeOpen()` provided [here](https://github.com/aquasecurity/tfsec/blob/master/internal/app/tfsec/cidr/cidr.go).
@@ -99,10 +83,8 @@ There is no longer a need to create dedicated tests for new checks - the `BadExa
 
 The first example that you add for Good and Bad will be used in the documentation, additional blocks you want to be tested to to verify the check should be added afterwards.
 
-
 And that's it! If you have any difficulties, please feel free to raise a draft PR and note any questions/problems in the description and we'll do our best to help you out.
 
-
 ### Submitting the PR
 
 When you are ready to submit the PR for review, please run 
diff --git a/internal/app/tfsec/adapter/azure/appservice/adapt.go b/internal/app/tfsec/adapter/azure/appservice/adapt.go
index 5ea9e6139..f317304fb 100644
--- a/internal/app/tfsec/adapter/azure/appservice/adapt.go
+++ b/internal/app/tfsec/adapter/azure/appservice/adapt.go
@@ -2,9 +2,91 @@ package appservice
 
 import (
 	"github.com/aquasecurity/defsec/provider/azure/appservice"
+	"github.com/aquasecurity/defsec/types"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 )
 
 func Adapt(modules []block.Module) appservice.AppService {
-	return appservice.AppService{}
+	return appservice.AppService{
+		Services:     adaptServices(modules),
+		FunctionApps: adaptFunctionApps(modules),
+	}
+}
+
+func adaptServices(modules []block.Module) []appservice.Service {
+	var services []appservice.Service
+
+	for _, module := range modules {
+		for _, resource := range module.GetResourcesByType("azurerm_app_service") {
+			services = append(services, adaptService(resource))
+		}
+	}
+	return services
+}
+
+func adaptFunctionApps(modules []block.Module) []appservice.FunctionApp {
+	var functionApps []appservice.FunctionApp
+
+	for _, module := range modules {
+		for _, resource := range module.GetResourcesByType("azurerm_function_app") {
+			functionApps = append(functionApps, adaptFunctionApp(resource))
+		}
+	}
+	return functionApps
+}
+
+func adaptService(resource block.Block) appservice.Service {
+	enableClientCertAttr := resource.GetAttribute("client_cert_enabled")
+	enableClientCertVal := enableClientCertAttr.AsBoolValueOrDefault(false, resource)
+
+	identityBlock := resource.GetBlock("identity")
+	typeVal := types.String("", *resource.GetMetadata())
+	if identityBlock.IsNotNil() {
+		typeAttr := identityBlock.GetAttribute("type")
+		typeVal = typeAttr.AsStringValueOrDefault("", identityBlock)
+	}
+
+	authBlock := resource.GetBlock("auth_settings")
+	enabledVal := types.Bool(false, *resource.GetMetadata())
+	if authBlock.IsNotNil() {
+		enabledAttr := authBlock.GetAttribute("enabled")
+		enabledVal = enabledAttr.AsBoolValueOrDefault(false, authBlock)
+	}
+
+	siteBlock := resource.GetBlock("site_config")
+	enableHTTP2Val := types.Bool(false, *resource.GetMetadata())
+	minTLSVersionVal := types.String("1.2", *resource.GetMetadata())
+	if siteBlock.IsNotNil() {
+		enableHTTP2Attr := siteBlock.GetAttribute("http2_enabled")
+		enableHTTP2Val = enableHTTP2Attr.AsBoolValueOrDefault(false, siteBlock)
+
+		minTLSVersionAttr := siteBlock.GetAttribute("min_tls_version")
+		minTLSVersionVal = minTLSVersionAttr.AsStringValueOrDefault("1.2", siteBlock)
+	}
+
+	return appservice.Service{
+		EnableClientCert: enableClientCertVal,
+		Identity: struct{ Type types.StringValue }{
+			Type: typeVal,
+		},
+		Authentication: struct{ Enabled types.BoolValue }{
+			Enabled: enabledVal,
+		},
+		Site: struct {
+			EnableHTTP2       types.BoolValue
+			MinimumTLSVersion types.StringValue
+		}{
+			EnableHTTP2:       enableHTTP2Val,
+			MinimumTLSVersion: minTLSVersionVal,
+		},
+	}
+}
+
+func adaptFunctionApp(resource block.Block) appservice.FunctionApp {
+	HTTPSOnlyAttr := resource.GetAttribute("https_only")
+	HTTPSOnlyVal := HTTPSOnlyAttr.AsBoolValueOrDefault(false, resource)
+
+	return appservice.FunctionApp{
+		HTTPSOnly: HTTPSOnlyVal,
+	}
 }
diff --git a/internal/app/tfsec/adapter/azure/compute/adapt.go b/internal/app/tfsec/adapter/azure/compute/adapt.go
index daa79c1bf..d95d9e160 100644
--- a/internal/app/tfsec/adapter/azure/compute/adapt.go
+++ b/internal/app/tfsec/adapter/azure/compute/adapt.go
@@ -1,10 +1,119 @@
 package compute
 
 import (
+	"encoding/base64"
+
 	"github.com/aquasecurity/defsec/provider/azure/compute"
+	"github.com/aquasecurity/defsec/types"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 )
 
 func Adapt(modules []block.Module) compute.Compute {
-	return compute.Compute{}
+	return adaptCompute(modules)
+}
+
+func adaptCompute(modules []block.Module) compute.Compute {
+
+	var managedDisks []compute.ManagedDisk
+	var linuxVirtualMachines []compute.LinuxVirtualMachine
+	var windowsVirtualMachines []compute.WindowsVirtualMachine
+
+	for _, module := range modules {
+
+		for _, resource := range module.GetResourcesByType("azurerm_linux_virtual_machine") {
+			linuxVirtualMachines = append(linuxVirtualMachines, adaptLinuxVM(resource))
+		}
+		for _, resource := range module.GetResourcesByType("azurerm_windows_virtual_machine") {
+			windowsVirtualMachines = append(windowsVirtualMachines, adaptWindowsVM(resource))
+		}
+		for _, resource := range module.GetResourcesByType("azurerm_virtual_machine") {
+			if resource.HasChild("os_profile_linux_config") {
+				linuxVirtualMachines = append(linuxVirtualMachines, adaptLinuxVM(resource))
+			} else if resource.HasChild("os_profile_windows_config") {
+				windowsVirtualMachines = append(windowsVirtualMachines, adaptWindowsVM(resource))
+			}
+		}
+		for _, resource := range module.GetResourcesByType("azurerm_managed_disk") {
+			managedDisks = append(managedDisks, adaptManagedDisk(resource))
+		}
+	}
+
+	return compute.Compute{
+		LinuxVirtualMachines:   linuxVirtualMachines,
+		WindowsVirtualMachines: windowsVirtualMachines,
+		ManagedDisks:           managedDisks,
+	}
+}
+
+func adaptManagedDisk(resource block.Block) compute.ManagedDisk {
+	encryptionBlock := resource.GetBlock("encryption_settings")
+	var enabledVal types.BoolValue
+
+	if encryptionBlock.IsNotNil() {
+		enabledAttr := encryptionBlock.GetAttribute("enabled")
+		enabledVal = enabledAttr.AsBoolValueOrDefault(false, encryptionBlock)
+	}
+
+	return compute.ManagedDisk{
+		Encryption: compute.Encryption{
+			Enabled: enabledVal,
+		},
+	}
+}
+
+func adaptLinuxVM(resource block.Block) compute.LinuxVirtualMachine {
+	workingBlock := resource
+
+	if resource.TypeLabel() == "azurerm_virtual_machine" {
+		workingBlock = resource.GetBlock("os_profile")
+	}
+	customDataAttr := workingBlock.GetAttribute("custom_data")
+	var customDataVal types.StringValue
+	if customDataAttr.IsResolvable() && customDataAttr.IsString() {
+		encoded, err := base64.StdEncoding.DecodeString(customDataAttr.Value().AsString())
+		if err != nil {
+			encoded = []byte(customDataAttr.Value().AsString())
+		}
+		customDataVal = types.String(string(encoded), *workingBlock.GetMetadata())
+	}
+
+	if resource.TypeLabel() == "azurerm_virtual_machine" {
+		workingBlock = resource.GetBlock("os_profile_linux_config")
+	}
+	disablePasswordAuthAttr := workingBlock.GetAttribute("disable_password_authentication")
+	disablePasswordAuthVal := disablePasswordAuthAttr.AsBoolValueOrDefault(true, workingBlock)
+
+	return compute.LinuxVirtualMachine{
+		VirtualMachine: compute.VirtualMachine{
+			CustomData: customDataVal,
+		},
+		OSProfileLinuxConfig: compute.OSProfileLinuxConfig{
+			DisablePasswordAuthentication: disablePasswordAuthVal,
+		},
+	}
+}
+
+func adaptWindowsVM(resource block.Block) compute.WindowsVirtualMachine {
+	workingBlock := resource
+
+	if resource.TypeLabel() == "azurerm_virtual_machine" {
+		workingBlock = resource.GetBlock("os_profile")
+	}
+
+	customDataAttr := workingBlock.GetAttribute("custom_data")
+	var customDataVal types.StringValue
+
+	if customDataAttr.IsResolvable() && customDataAttr.IsString() {
+		encoded, err := base64.StdEncoding.DecodeString(customDataAttr.Value().AsString())
+		if err != nil {
+			encoded = []byte(customDataAttr.Value().AsString())
+		}
+		customDataVal = types.String(string(encoded), *workingBlock.GetMetadata())
+	}
+
+	return compute.WindowsVirtualMachine{
+		VirtualMachine: compute.VirtualMachine{
+			CustomData: customDataVal,
+		},
+	}
 }
diff --git a/internal/app/tfsec/block/type.go b/internal/app/tfsec/block/type.go
index 05ee86f26..6c0fb7987 100644
--- a/internal/app/tfsec/block/type.go
+++ b/internal/app/tfsec/block/type.go
@@ -38,6 +38,10 @@ var TypeLocal = Type{
 	refName: "local",
 }
 
+var TypeMoved = Type{
+	name: "moved",
+}
+
 var TypeProvider = Type{
 	name: "provider",
 }
@@ -58,6 +62,7 @@ var ValidTypes = []Type{
 	TypeData,
 	TypeLocal,
 	TypeModule,
+	TypeMoved,
 	TypeOutput,
 	TypeProvider,
 	TypeResource,
diff --git a/internal/app/tfsec/parser/evaluator.go b/internal/app/tfsec/parser/evaluator.go
index 89d918fd3..a12bffedb 100644
--- a/internal/app/tfsec/parser/evaluator.go
+++ b/internal/app/tfsec/parser/evaluator.go
@@ -399,7 +399,7 @@ func (e *Evaluator) getValuesByBlockType(blockType string) cty.Value {
 				continue
 			}
 			values[b.Label()] = val
-		case "locals":
+		case "locals", "moved":
 			for key, val := range b.Values().AsValueMap() {
 				values[key] = val
 			}
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
index 0fff9cd47..dbe920411 100644
--- a/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule.go
+++ b/internal/app/tfsec/rules/azure/appservice/account_identity_registered_rule.go
@@ -1,9 +1,7 @@
 package appservice
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/appservice"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -41,11 +39,5 @@ func init() {
 			"azurerm_app_service",
 		},
 		Base: appservice.CheckAccountIdentityRegistered,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			if identityAttr := resourceBlock.GetBlock("identity"); identityAttr.IsNil() { // alert on use of default value
-				results.Add("Resource does not set identity", resourceBlock)
-			}
-			return results
-		},
 	})
 }
diff --git a/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go b/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go
index ec7ac3544..ed1eb430d 100644
--- a/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go
+++ b/internal/app/tfsec/rules/azure/appservice/authentication_enabled_rule.go
@@ -1,9 +1,7 @@
 package appservice
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/appservice"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -40,15 +38,5 @@ func init() {
 			"azurerm_app_service",
 		},
 		Base: appservice.CheckAuthenticationEnabled,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			if authBlock := resourceBlock.GetBlock("auth_settings"); authBlock.IsNil() {
-				results.Add("Resource uses default value for auth_settings.enabled", resourceBlock)
-			} else if enabledAttr := authBlock.GetAttribute("enabled"); enabledAttr.IsNil() {
-				results.Add("Resource uses default value for auth_settings.enabled", authBlock)
-			} else if enabledAttr.IsFalse() {
-				results.Add("Resource has attribute auth_settings.enabled that is false", enabledAttr)
-			}
-			return results
-		},
 	})
 }
diff --git a/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go b/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go
index 804472301..df66fcd34 100644
--- a/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go
+++ b/internal/app/tfsec/rules/azure/appservice/enable_http2_rule.go
@@ -1,9 +1,7 @@
 package appservice
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/appservice"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -51,15 +49,5 @@ func init() {
 			"azurerm_app_service",
 		},
 		Base: appservice.CheckEnableHttp2,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			if configBlock := resourceBlock.GetBlock("site_config"); configBlock.IsNil() {
-				results.Add("Resource uses default value for site_config.http2_enabled", resourceBlock)
-			} else if http2EnabledAttr := configBlock.GetAttribute("http2_enabled"); http2EnabledAttr.IsNil() { // alert on use of default value
-				results.Add("Resource uses default value for site_config.http2_enabled", configBlock)
-			} else if http2EnabledAttr.IsFalse() {
-				results.Add("Resource has attribute site_config.http2_enabled that is false", http2EnabledAttr)
-			}
-			return results
-		},
 	})
 }
diff --git a/internal/app/tfsec/rules/azure/appservice/enforce_https_rule.go b/internal/app/tfsec/rules/azure/appservice/enforce_https_rule.go
index 2aeef5f60..ca072aa57 100644
--- a/internal/app/tfsec/rules/azure/appservice/enforce_https_rule.go
+++ b/internal/app/tfsec/rules/azure/appservice/enforce_https_rule.go
@@ -1,9 +1,7 @@
 package appservice
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/appservice"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -40,15 +38,5 @@ func init() {
 		RequiredTypes:  []string{"resource"},
 		RequiredLabels: []string{"azurerm_function_app"},
 		Base:           appservice.CheckEnforceHttps,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			if resourceBlock.MissingChild("https_only") {
-				results.Add("Resource should have https_only set to true, the default is false.", resourceBlock)
-				return
-			}
-			if httpsOnlyAttr := resourceBlock.GetAttribute("https_only"); httpsOnlyAttr.IsFalse() {
-				results.Add("Resource should be HTTPS only.", httpsOnlyAttr)
-			}
-			return results
-		},
 	})
 }
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
index cba20964b..dc45bcd8f 100644
--- a/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule.go
+++ b/internal/app/tfsec/rules/azure/appservice/require_client_cert_rule.go
@@ -1,9 +1,7 @@
 package appservice
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/appservice"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -47,13 +45,5 @@ func init() {
 			"azurerm_app_service",
 		},
 		Base: appservice.CheckRequireClientCert,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			if clientCertEnabledAttr := resourceBlock.GetAttribute("client_cert_enabled"); clientCertEnabledAttr.IsNil() { // alert on use of default value
-				results.Add("Resource uses default value for client_cert_enabled", resourceBlock)
-			} else if clientCertEnabledAttr.IsFalse() {
-				results.Add("Resource has attribute client_cert_enabled that is false", clientCertEnabledAttr)
-			}
-			return results
-		},
 	})
 }
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
index 5ed498887..7f037caf1 100644
--- 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
@@ -1,9 +1,7 @@
 package appservice
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/appservice"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -40,15 +38,5 @@ func init() {
 			"azurerm_app_service",
 		},
 		Base: appservice.CheckUseSecureTlsPolicy,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			if resourceBlock.MissingChild("site_config") {
-				return
-			}
-
-			if minTlsVersionAttr := resourceBlock.GetBlock("site_config").GetAttribute("min_tls_version"); minTlsVersionAttr.IsNotNil() && minTlsVersionAttr.NotEqual("1.2") {
-				results.Add("Resource does not have site_config.min_tls_version set to 1.2", minTlsVersionAttr)
-			}
-			return results
-		},
 	})
 }
diff --git a/internal/app/tfsec/rules/azure/compute/disable_password_authentication_rule.go b/internal/app/tfsec/rules/azure/compute/disable_password_authentication_rule.go
index 26ac2c1f0..40c61748a 100644
--- a/internal/app/tfsec/rules/azure/compute/disable_password_authentication_rule.go
+++ b/internal/app/tfsec/rules/azure/compute/disable_password_authentication_rule.go
@@ -1,9 +1,7 @@
 package compute
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/compute"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -80,24 +78,5 @@ func init() {
 		RequiredTypes:  []string{"resource"},
 		RequiredLabels: []string{"azurerm_linux_virtual_machine", "azurerm_virtual_machine"},
 		Base:           compute.CheckDisablePasswordAuthentication,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-
-			workingBlock := resourceBlock
-			if resourceBlock.TypeLabel() == "azurerm_virtual_machine" {
-				if resourceBlock.HasChild("os_profile_linux_config") {
-					workingBlock = resourceBlock.GetBlock("os_profile_linux_config")
-				}
-			}
-
-			if workingBlock.MissingChild("disable_password_authentication") {
-				return
-			}
-
-			passwordAuthAttr := workingBlock.GetAttribute("disable_password_authentication")
-			if passwordAuthAttr.IsFalse() {
-				results.Add("Resource has password authentication enabled.", passwordAuthAttr)
-			}
-			return results
-		},
 	})
 }
diff --git a/internal/app/tfsec/rules/azure/compute/enable_disk_encryption_rule.go b/internal/app/tfsec/rules/azure/compute/enable_disk_encryption_rule.go
index 7eff1f597..2a4ae80d1 100644
--- a/internal/app/tfsec/rules/azure/compute/enable_disk_encryption_rule.go
+++ b/internal/app/tfsec/rules/azure/compute/enable_disk_encryption_rule.go
@@ -1,9 +1,7 @@
 package compute
 
 import (
-	"github.com/aquasecurity/defsec/rules"
 	"github.com/aquasecurity/defsec/rules/azure/compute"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
 )
@@ -29,22 +27,5 @@ func init() {
 		RequiredTypes:  []string{"resource"},
 		RequiredLabels: []string{"azurerm_managed_disk"},
 		Base:           compute.CheckEnableDiskEncryption,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-			encryptionSettingsBlock := resourceBlock.GetBlock("encryption_settings")
-			if encryptionSettingsBlock.IsNil() {
-				return // encryption is by default now, so this is fine
-			}
-
-			if encryptionSettingsBlock.MissingChild("enabled") {
-				return
-			}
-
-			enabledAttr := encryptionSettingsBlock.GetAttribute("enabled")
-			if enabledAttr.IsFalse() {
-				results.Add("Resource defines an unencrypted managed disk.", enabledAttr)
-			}
-
-			return results
-		},
 	})
 }
diff --git a/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule.go b/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule.go
index 92f9f0629..d51ebcd1e 100644
--- a/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule.go
+++ b/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule.go
@@ -1,16 +1,10 @@
 package compute
 
 import (
-	"encoding/base64"
-
 	"github.com/aquasecurity/defsec/rules/azure/compute"
 
-	"github.com/aquasecurity/defsec/rules"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/block"
-	"github.com/aquasecurity/tfsec/internal/app/tfsec/debug"
 	"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner"
 	"github.com/aquasecurity/tfsec/pkg/rule"
-	"github.com/owenrumney/squealer/pkg/squealer"
 )
 
 func init() {
@@ -18,17 +12,27 @@ func init() {
 		BadExample: []string{`
  resource "azurerm_virtual_machine" "bad_example" {
  	name = "bad_example"
- 	custom_data =<<EOF
- export DATABASE_PASSWORD=\"SomeSortOfPassword\"
- EOF
+	os_profile_linux_config {
+		disable_password_authentication = false
+	}
+	os_profile {
+		custom_data =<<EOF
+			export DATABASE_PASSWORD=\"SomeSortOfPassword\"
+			EOF
+	}
  }
  `},
 		GoodExample: []string{`
  resource "azurerm_virtual_machine" "good_example" {
  	name = "good_example"
- 	custom_data =<<EOF
- export GREETING="Hello there"
- EOF
+	os_profile_linux_config {
+		disable_password_authentication = false
+	}
+	os_profile {
+		custom_data =<<EOF
+			export GREETING="Hello there"
+			EOF
+	}
  }
  `},
 		Links: []string{
@@ -37,36 +41,5 @@ func init() {
 		RequiredTypes:  []string{"resource"},
 		RequiredLabels: []string{"azurerm_virtual_machine", "azurerm_linux_virtual_machine", "azurerm_windows_virtual_machine"},
 		Base:           compute.CheckNoSecretsInCustomData,
-		CheckTerraform: func(resourceBlock block.Block, _ block.Module) (results rules.Results) {
-
-			if resourceBlock.MissingChild("custom_data") {
-				return
-			}
-
-			customDataAttr := resourceBlock.GetAttribute("custom_data")
-
-			if resourceBlock.TypeLabel() == "azurerm_virtual_machine" {
-				for _, str := range customDataAttr.ValueAsStrings() {
-					if checkStringForSensitive(str) {
-						results.Add("Resource has custom_data with sensitive data.", customDataAttr)
-					}
-				}
-			} else if customDataAttr.IsResolvable() && customDataAttr.IsString() {
-				encoded, err := base64.StdEncoding.DecodeString(customDataAttr.Value().AsString())
-				if err != nil {
-					debug.Log("could not decode the base64 string in the terraform, trying with the string verbatim")
-					encoded = []byte(customDataAttr.Value().AsString())
-				}
-				if checkStringForSensitive(string(encoded)) {
-					results.Add("Resource has custom_data with sensitive data.", customDataAttr)
-				}
-
-			}
-			return results
-		},
 	})
 }
-
-func checkStringForSensitive(stringToCheck string) bool {
-	return squealer.NewStringScanner().Scan(stringToCheck).TransgressionFound
-}
diff --git a/internal/app/tfsec/schema/schema.go b/internal/app/tfsec/schema/schema.go
index 2f8d3023a..9920a7a15 100644
--- a/internal/app/tfsec/schema/schema.go
+++ b/internal/app/tfsec/schema/schema.go
@@ -19,6 +19,9 @@ var TerraformSchema_0_12 = &hcl.BodySchema{
 		{
 			Type: "locals",
 		},
+		{
+			Type: "moved",
+		},
 		{
 			Type:       "output",
 			LabelNames: []string{"name"},


Test patch:
diff --git a/internal/app/tfsec/parser/parser_test.go b/internal/app/tfsec/parser/parser_test.go
index b7cb16484..316d7c503 100644
--- a/internal/app/tfsec/parser/parser_test.go
+++ b/internal/app/tfsec/parser/parser_test.go
@@ -32,6 +32,10 @@ provider "cats" {
 
 }
 
+moved {
+
+}
+
 resource "cats_cat" "mittens" {
 	name = "mittens"
 	special = true
diff --git a/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule_test.go b/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule_test.go
index 8b1687032..115866297 100644
--- a/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule_test.go
+++ b/internal/app/tfsec/rules/azure/compute/no_secrets_in_custom_data_rule_test.go
@@ -20,9 +20,14 @@ func Test_AzureNoSecretsInCustomData(t *testing.T) {
 			source: `
  			resource "azurerm_virtual_machine" "bad_example" {
  				name = "bad_example"
- 				custom_data =<<EOF
- DATABASE_PASSWORD=SomeSortOfPassword
- EOF
+				os_profile_windows_config {
+					disable_password_authentication = false
+				}
+				os_profile {
+					custom_data =<<EOF
+						DATABASE_PASSWORD=SomeSortOfPassword
+						EOF
+				}
  			}
  `,
 			mustIncludeResultCode: expectedCode,
@@ -32,9 +37,14 @@ func Test_AzureNoSecretsInCustomData(t *testing.T) {
 			source: `
  			resource "azurerm_virtual_machine" "bad_example" {
  				name = "bad_example"
- 				custom_data =<<EOF
- DATABASE_PASSWORD="SomeSortOfPassword"
- EOF
+				os_profile_windows_config {
+					disable_password_authentication = false
+				}
+				os_profile {
+ 					custom_data =<<EOF
+ 						DATABASE_PASSWORD="SomeSortOfPassword"
+ 						EOF
+				}
  			}
  `,
 			mustIncludeResultCode: expectedCode,
@@ -52,11 +62,16 @@ func Test_AzureNoSecretsInCustomData(t *testing.T) {
 		{
 			name: "virtual machine with no sensitive information in custom_data passes check",
 			source: `
- resource "azurerm_virtual_machine" "god_example" {
+ resource "azurerm_virtual_machine" "good_example" {
  				name = "good_example"
- 				custom_data =<<EOF
- GREETING_TEXT="Hello"
- EOF
+				os_profile_windows_config {
+					disable_password_authentication = false
+				}
+				os_profile {
+					custom_data =<<EOF
+						GREETING_TEXT="Hello"
+						EOF
+				}
  			}
  `,
 			mustExcludeResultCode: expectedCode,
@@ -64,7 +79,7 @@ func Test_AzureNoSecretsInCustomData(t *testing.T) {
 		{
 			name: "linux virtual machine with no sensitive information in base64 custom_data passes check",
 			source: `
- resource "azurerm_linux_virtual_machine" "god_example" {
+ resource "azurerm_linux_virtual_machine" "good_example" {
  				name = "good_example"
  				custom_data = "ZXhwb3J0IEVESVRPUj12aW1hY3M=" 
  			}