diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/metadata.json b/assets/queries/terraform/azure/vm_without_managed_disk/metadata.json new file mode 100644 index 00000000000..378a38d331e --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/metadata.json @@ -0,0 +1,14 @@ +{ + "id": "0536c90c-714e-4184-991e-3fed8d8b7b46", + "queryName": "Beta - VM Without Managed Disk", + "severity": "MEDIUM", + "category": "Resource Management", + "descriptionText": "Virtual machine resources should set a managed disk for encryption, resilience and reduction of costs", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_virtual_machine", + "platform": "Terraform", + "descriptionID": "0536c90c", + "cloudProvider": "azure", + "cwe": "922", + "riskScore": "3.0", + "experimental": "true" +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/query.rego b/assets/queries/terraform/azure/vm_without_managed_disk/query.rego new file mode 100644 index 00000000000..c5f5f0117f0 --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/query.rego @@ -0,0 +1,66 @@ +package Cx + +import data.generic.common as common_lib +import data.generic.terraform as tf_lib + +types := {"azurerm_virtual_machine", "azurerm_linux_virtual_machine", "azurerm_windows_virtual_machine"} + +CxPolicy[result] { + resource := input.document[i].resource[types[t]][name] + + results := get_results(resource, name, types[t]) + + result := { + "documentId": input.document[i].id, + "resourceType": types[t], + "resourceName": tf_lib.get_resource_name(resource, name), + "searchKey": results.searchKey, + "issueType": results.issueType, + "keyExpectedValue": results.keyExpectedValue, + "keyActualValue": results.keyActualValue, + "searchLine": results.searchLine + } +} + +get_results(resource, name, type) = results { + type == "azurerm_virtual_machine" + not common_lib.valid_key(resource, "storage_os_disk") + results := { + "searchKey": sprintf("azurerm_virtual_machine[%s]", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("'azurerm_virtual_machine[%s].storage_os_disk' should be defined and not null", [name]), + "keyActualValue": sprintf("'azurerm_virtual_machine[%s].storage_os_disk' is undefined or null", [name]), + "searchLine": common_lib.build_search_line(["resource", "azurerm_virtual_machine", name], []) + } +} else = results { + type == "azurerm_virtual_machine" + common_lib.valid_key(resource.storage_os_disk, "vhd_uri") + results := { + "searchKey": sprintf("azurerm_virtual_machine[%s].storage_os_disk.vhd_uri", [name]), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("'azurerm_virtual_machine[%s].storage_os_disk.vhd_uri' should not be set", [name]), + "keyActualValue": sprintf("'azurerm_virtual_machine[%s].storage_os_disk.vhd_uri' is set", [name]), + "searchLine": common_lib.build_search_line(["resource", "azurerm_virtual_machine", name, "storage_os_disk", "vhd_uri"], []) + } +} else = results { + type == "azurerm_virtual_machine" + not common_lib.valid_key(resource.storage_os_disk, "managed_disk_id") + not common_lib.valid_key(resource.storage_os_disk, "managed_disk_type") + results := { + "searchKey": sprintf("azurerm_virtual_machine[%s].storage_os_disk", [name]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("'azurerm_virtual_machine[%s].storage_os_disk' should define a 'managed_disk_id' or 'managed_disk_type'", [name]), + "keyActualValue": sprintf("'azurerm_virtual_machine[%s].storage_os_disk' does not define or sets to null 'managed_disk_id' and 'managed_disk_type'", [name]), + "searchLine": common_lib.build_search_line(["resource", "azurerm_virtual_machine", name, "storage_os_disk"], []) + } +} else = results { + type != "azurerm_virtual_machine" + not common_lib.valid_key(resource, "os_managed_disk_id") + results := { + "searchKey": sprintf("%s[%s]", [type, name]), + "issueType": "MissingAttribute", + "keyExpectedValue": sprintf("'%s[%s].os_managed_disk_id' should be defined and not null", [type, name]), + "keyActualValue": sprintf("'%s[%s].os_managed_disk_id' is undefined or null", [type, name]), + "searchLine": common_lib.build_search_line(["resource", type, name], []) + } +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/negative1.tf b/assets/queries/terraform/azure/vm_without_managed_disk/test/negative1.tf new file mode 100644 index 00000000000..a59e49ff0f6 --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/negative1.tf @@ -0,0 +1,29 @@ +resource "azurerm_virtual_machine" "main" { + name = "${var.prefix}-vm" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + network_interface_ids = [azurerm_network_interface.main.id] + vm_size = "Standard_DS1_v2" + + storage_os_disk { + name = "myosdisk1" + caching = "ReadWrite" + create_option = "FromImage" + managed_disk_type = "Standard_LRS" + } +} + +resource "azurerm_virtual_machine" "main" { + name = "${var.prefix}-vm" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + network_interface_ids = [azurerm_network_interface.main.id] + vm_size = "Standard_DS1_v2" + + storage_os_disk { + name = "myosdisk1" + caching = "ReadWrite" + create_option = "Attach" + managed_disk_id = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Compute/disks/myManagedDisk" + } +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/negative2.tf b/assets/queries/terraform/azure/vm_without_managed_disk/test/negative2.tf new file mode 100644 index 00000000000..5e07fd2491f --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/negative2.tf @@ -0,0 +1,9 @@ +resource "azurerm_linux_virtual_machine" "negative2" { + name = "negative2-machine" + resource_group_name = azurerm_resource_group.negative2.name + location = azurerm_resource_group.negative2.location + size = "Standard_F2" + admin_username = "adminuser" + + os_managed_disk_id = azurerm_managed_disk.negative2.id +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/negative3.tf b/assets/queries/terraform/azure/vm_without_managed_disk/test/negative3.tf new file mode 100644 index 00000000000..ad5ffba1e68 --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/negative3.tf @@ -0,0 +1,9 @@ +resource "azurerm_windows_virtual_machine" "negative3" { + name = "negative3-machine" + resource_group_name = azurerm_resource_group.negative3.name + location = azurerm_resource_group.negative3.location + size = "Standard_F2" + admin_username = "adminuser" + + os_managed_disk_id = azurerm_managed_disk.negative3.id +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/positive1.tf b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive1.tf new file mode 100644 index 00000000000..8cc500b063c --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive1.tf @@ -0,0 +1,39 @@ +resource "azurerm_virtual_machine" "positive1" { + name = "${var.prefix}-vm" + location = azurerm_resource_group.positive1.location + resource_group_name = azurerm_resource_group.positive1.name + network_interface_ids = [azurerm_network_interface.main.id] + vm_size = "Standard_DS1_v2" + + # missing "storage_os_disk" (tecnically required) +} + +resource "azurerm_virtual_machine" "positive2" { + name = "${var.prefix}-vm" + location = azurerm_resource_group.positive2.location + resource_group_name = azurerm_resource_group.positive2.name + network_interface_ids = [azurerm_network_interface.main.id] + vm_size = "Standard_DS1_v2" + + storage_os_disk { + name = "myosdisk1" + create_option = "FromImage" + vhd_uri = "https://.blob.core.windows.net//.vhd" + # unmanaged disk + } +} + +resource "azurerm_virtual_machine" "positive3" { + name = "${var.prefix}-vm" + location = azurerm_resource_group.positive3.location + resource_group_name = azurerm_resource_group.positive3.name + network_interface_ids = [azurerm_network_interface.main.id] + vm_size = "Standard_DS1_v2" + + + storage_os_disk { + name = "myosdisk1" + create_option = "FromImage" + # missing managed_disk_type/managed_disk_id + } +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/positive2.tf b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive2.tf new file mode 100644 index 00000000000..7f4e383ade5 --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive2.tf @@ -0,0 +1,9 @@ +resource "azurerm_linux_virtual_machine" "positive2" { + name = "positive2-machine" + resource_group_name = azurerm_resource_group.positive2.name + location = azurerm_resource_group.positive2.location + size = "Standard_F2" + admin_username = "adminuser" + + # missing os_managed_disk_id +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/positive3.tf b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive3.tf new file mode 100644 index 00000000000..d4271363318 --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive3.tf @@ -0,0 +1,9 @@ +resource "azurerm_windows_virtual_machine" "positive3" { + name = "positive3-machine" + resource_group_name = azurerm_resource_group.positive3.name + location = azurerm_resource_group.positive3.location + size = "Standard_F2" + admin_username = "adminuser" + + # missing os_managed_disk_id +} diff --git a/assets/queries/terraform/azure/vm_without_managed_disk/test/positive_expected_result.json b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive_expected_result.json new file mode 100644 index 00000000000..a21daea1b79 --- /dev/null +++ b/assets/queries/terraform/azure/vm_without_managed_disk/test/positive_expected_result.json @@ -0,0 +1,32 @@ +[ + { + "queryName": "Beta - VM Without Managed Disk", + "severity": "MEDIUM", + "line": 1, + "filename": "positive1.tf" + }, + { + "queryName": "Beta - VM Without Managed Disk", + "severity": "MEDIUM", + "line": 21, + "filename": "positive1.tf" + }, + { + "queryName": "Beta - VM Without Managed Disk", + "severity": "MEDIUM", + "line": 34, + "filename": "positive1.tf" + }, + { + "queryName": "Beta - VM Without Managed Disk", + "severity": "MEDIUM", + "line": 1, + "filename": "positive2.tf" + }, + { + "queryName": "Beta - VM Without Managed Disk", + "severity": "MEDIUM", + "line": 1, + "filename": "positive3.tf" + } +] diff --git a/assets/similarityID_transition/terraform_azure.yaml b/assets/similarityID_transition/terraform_azure.yaml index 407c810f4d1..d5b1c99352c 100644 --- a/assets/similarityID_transition/terraform_azure.yaml +++ b/assets/similarityID_transition/terraform_azure.yaml @@ -3,3 +3,7 @@ similarityIDChangeList: queryName: Sensitive Port Is Exposed To Wide Private Network observations: "" change: 5 + - queryId: 0536c90c-714e-4184-991e-3fed8d8b7b46 + queryName: Beta - VM Without Managed Disk + observations: "" + change: 2