From e732e215a16c3c6589eed6990a78fb1bdc655189 Mon Sep 17 00:00:00 2001 From: James Woolfenden Date: Wed, 18 Oct 2023 15:10:19 +0100 Subject: [PATCH] feat(arm): implement CKV_AZURE_97 for ARM (#5515) * feat(arm): implement CKV_AZURE_97 for ARM * fix json * fix json * adjust logic --------- Co-authored-by: gruebel --- .../resource/VMEncryptionAtHostEnabled.py | 37 +++ .../azure/VMEncryptionAtHostEnabled.py | 4 +- .../scaleset-fail.json | 252 ++++++++++++++++++ .../scaleset-fail2.json | 249 +++++++++++++++++ .../scaleset-pass.json | 252 ++++++++++++++++++ .../vm-fail.json | 161 +++++++++++ .../vm-fail2.json | 158 +++++++++++ .../vm-pass.json | 161 +++++++++++ .../test_VMEncryptionAtHostEnabled.py | 44 +++ 9 files changed, 1316 insertions(+), 2 deletions(-) create mode 100644 checkov/arm/checks/resource/VMEncryptionAtHostEnabled.py create mode 100644 tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail.json create mode 100644 tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail2.json create mode 100644 tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-pass.json create mode 100644 tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail.json create mode 100644 tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail2.json create mode 100644 tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-pass.json create mode 100644 tests/arm/checks/resource/test_VMEncryptionAtHostEnabled.py diff --git a/checkov/arm/checks/resource/VMEncryptionAtHostEnabled.py b/checkov/arm/checks/resource/VMEncryptionAtHostEnabled.py new file mode 100644 index 00000000000..3541deacf5b --- /dev/null +++ b/checkov/arm/checks/resource/VMEncryptionAtHostEnabled.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from checkov.common.models.enums import CheckCategories, CheckResult +from checkov.arm.base_resource_check import BaseResourceCheck + +from typing import Any + +from checkov.common.util.data_structures_utils import find_in_dict + + +class VMEncryptionAtHostEnabled(BaseResourceCheck): + def __init__(self) -> None: + name = "Ensure that Virtual machine scale sets have encryption at host enabled" + id = "CKV_AZURE_97" + supported_resources = ("Microsoft.Compute/virtualMachineScaleSets", "Microsoft.Compute/virtualMachines") + categories = (CheckCategories.ENCRYPTION,) + super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources) + + def scan_resource_conf(self, conf: dict[str, Any]) -> CheckResult: + encryption = "" + + if self.entity_type == "Microsoft.Compute/virtualMachines": + self.evaluated_keys = ["properties/securityProfile/encryptionAtHost"] + encryption = find_in_dict(input_dict=conf, key_path="properties/securityProfile/encryptionAtHost") + elif self.entity_type == "Microsoft.Compute/virtualMachineScaleSets": + self.evaluated_keys = ["properties/virtualMachineProfile/securityProfile/encryptionAtHost"] + encryption = find_in_dict( + input_dict=conf, key_path="properties/virtualMachineProfile/securityProfile/encryptionAtHost" + ) + + if encryption == "true": + return CheckResult.PASSED + + return CheckResult.FAILED + + +check = VMEncryptionAtHostEnabled() diff --git a/checkov/terraform/checks/resource/azure/VMEncryptionAtHostEnabled.py b/checkov/terraform/checks/resource/azure/VMEncryptionAtHostEnabled.py index 28ac3395c83..66dd0e13933 100644 --- a/checkov/terraform/checks/resource/azure/VMEncryptionAtHostEnabled.py +++ b/checkov/terraform/checks/resource/azure/VMEncryptionAtHostEnabled.py @@ -3,14 +3,14 @@ class VMEncryptionAtHostEnabled(BaseResourceValueCheck): - def __init__(self): + def __init__(self) -> None: name = "Ensure that Virtual machine scale sets have encryption at host enabled" id = "CKV_AZURE_97" supported_resources = ['azurerm_linux_virtual_machine_scale_set', 'azurerm_windows_virtual_machine_scale_set'] categories = [CheckCategories.ENCRYPTION] super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources) - def get_inspected_key(self): + def get_inspected_key(self) -> str: return 'encryption_at_host_enabled' diff --git a/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail.json b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail.json new file mode 100644 index 00000000000..85328068544 --- /dev/null +++ b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail.json @@ -0,0 +1,252 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmSize": { + "type": "string", + "defaultValue": "Standard_DS3_V2", + "metadata": { + "description": "Size of VMs in the VM Scale Set." + } + }, + "windowsOSVersion": { + "type": "string", + "defaultValue": "2012-R2-Datacenter", + "allowedValues": [ + "2008-R2-SP1", + "2012-Datacenter", + "2012-R2-Datacenter" + ], + "metadata": { + "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter." + } + }, + "vmssName": { + "type": "string", + "maxLength": 9 + }, + "instanceCount": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "Number of VM instances (100 or less)." + }, + "maxValue": 100 + }, + "adminUsername": { + "type": "string", + "defaultValue": "adminUserIsTest", + "metadata": { + "description": "Admin username on all VMs." + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Admin password on all VMs." + } + } + , + "diskEncryptionSetId": { + "type": "string", + "defaultValue": "" + }, + "region": { + "type": "string", + "defaultValue": "CentralUSEUAP" + } + }, + "variables": { + "namingInfix": "[toLower(parameters('vmssName'))]", + "addressPrefix": "10.0.0.0/16", + "subnetPrefix": "10.0.0.0/24", + "virtualNetworkName": "[concat(variables('namingInfix'), 'vnet')]", + "publicIPAddressName": "[concat(variables('namingInfix'), 'pip')]", + "subnetName": "[concat(variables('namingInfix'), 'subnet')]", + "loadBalancerName": "[concat(variables('namingInfix'), 'lb')]", + "publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]", + "lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('loadBalancerName'))]", + "natPoolName": "[concat(variables('namingInfix'), 'natpool')]", + "bePoolName": "[concat(variables('namingInfix'), 'bepool')]", + "natStartPort": 50000, + "natEndPort": 50119, + "natBackendPort": 3389, + "nicName": "[concat(variables('namingInfix'), 'nic')]", + "ipConfigName": "[concat(variables('namingInfix'), 'ipconfig')]", + "frontEndIPConfigID": "[concat(variables('lbID'),'/frontendIPConfigurations/loadBalancerFrontEnd')]", + "osType": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "[parameters('windowsOSVersion')]", + "version": "latest" + }, + "imageReference": "[variables('osType')]" + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('virtualNetworkName')]", + "location": "[parameters('region')]", + "apiVersion": "2019-06-01", + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "addressPrefix": "[variables('subnetPrefix')]" + } + } + ] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "name": "[variables('publicIPAddressName')]", + "location": "[parameters('region')]", + "apiVersion": "2019-06-01", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "properties": { + "publicIPAllocationMethod": "Dynamic", + "dnsSettings": { + "domainNameLabel": "[variables('namingInfix')]" + } + } + }, + { + "type": "Microsoft.Network/loadBalancers", + "name": "[variables('loadBalancerName')]", + "location": "[parameters('region')]", + "apiVersion": "2020-03-01", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerFrontEnd", + "properties": { + "publicIPAddress": { + "id": "[variables('publicIPAddressID')]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "[variables('bePoolName')]" + } + ], + "inboundNatPools": [ + { + "name": "[variables('natPoolName')]", + "properties": { + "frontendIPConfiguration": { + "id": "[variables('frontEndIPConfigID')]" + }, + "protocol": "Tcp", + "frontendPortRangeStart": "[variables('natStartPort')]", + "frontendPortRangeEnd": "[variables('natEndPort')]", + "backendPort": "[variables('natBackendPort')]" + } + } + ] + } + }, + { + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "fail", + "location": "[parameters('region')]", + "apiVersion": "2020-06-01", + "dependsOn": [ + "[concat('Microsoft.Network/loadBalancers/', variables('loadBalancerName'))]", + "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]" + ], + "sku": { + "name": "[parameters('vmSize')]", + "tier": "Standard", + "capacity": "[parameters('instanceCount')]" + }, + "properties": { + "overprovision": "true", + "upgradePolicy": { + "mode": "Manual" + }, + "virtualMachineProfile": { + "storageProfile": { + "osDisk": { + "createOption": "FromImage", + "caching": "ReadWrite", + "managedDisk": { + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + }, + "storageAccountType": "Premium_LRS" + } + }, + "dataDisks": [ + { + "lun": 0, + "createOption": "Empty", + "caching": "None", + "managedDisk": { + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + }, + "storageAccountType": "Premium_LRS" + }, + "diskSizeGB": 64 + } + ], + "imageReference": "[variables('imageReference')]" + }, + "securityProfile":{ + "encryptionAtHost": "false" + }, + "osProfile": { + "computerNamePrefix": "[variables('namingInfix')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[variables('nicName')]", + "properties": { + "primary": true, + "ipConfigurations": [ + { + "name": "[variables('ipConfigName')]", + "properties": { + "subnet": { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'), '/subnets/', variables('subnetName'))]" + }, + "loadBalancerBackendAddressPools": [ + { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/backendAddressPools/', variables('bePoolName'))]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/inboundNatPools/', variables('natPoolName'))]" + } + ] + } + } + ] + } + } + ] + } + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail2.json b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail2.json new file mode 100644 index 00000000000..4628285ca4b --- /dev/null +++ b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-fail2.json @@ -0,0 +1,249 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmSize": { + "type": "string", + "defaultValue": "Standard_DS3_V2", + "metadata": { + "description": "Size of VMs in the VM Scale Set." + } + }, + "windowsOSVersion": { + "type": "string", + "defaultValue": "2012-R2-Datacenter", + "allowedValues": [ + "2008-R2-SP1", + "2012-Datacenter", + "2012-R2-Datacenter" + ], + "metadata": { + "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter." + } + }, + "vmssName": { + "type": "string", + "maxLength": 9 + }, + "instanceCount": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "Number of VM instances (100 or less)." + }, + "maxValue": 100 + }, + "adminUsername": { + "type": "string", + "defaultValue": "adminUserIsTest", + "metadata": { + "description": "Admin username on all VMs." + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Admin password on all VMs." + } + } + , + "diskEncryptionSetId": { + "type": "string", + "defaultValue": "" + }, + "region": { + "type": "string", + "defaultValue": "CentralUSEUAP" + } + }, + "variables": { + "namingInfix": "[toLower(parameters('vmssName'))]", + "addressPrefix": "10.0.0.0/16", + "subnetPrefix": "10.0.0.0/24", + "virtualNetworkName": "[concat(variables('namingInfix'), 'vnet')]", + "publicIPAddressName": "[concat(variables('namingInfix'), 'pip')]", + "subnetName": "[concat(variables('namingInfix'), 'subnet')]", + "loadBalancerName": "[concat(variables('namingInfix'), 'lb')]", + "publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]", + "lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('loadBalancerName'))]", + "natPoolName": "[concat(variables('namingInfix'), 'natpool')]", + "bePoolName": "[concat(variables('namingInfix'), 'bepool')]", + "natStartPort": 50000, + "natEndPort": 50119, + "natBackendPort": 3389, + "nicName": "[concat(variables('namingInfix'), 'nic')]", + "ipConfigName": "[concat(variables('namingInfix'), 'ipconfig')]", + "frontEndIPConfigID": "[concat(variables('lbID'),'/frontendIPConfigurations/loadBalancerFrontEnd')]", + "osType": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "[parameters('windowsOSVersion')]", + "version": "latest" + }, + "imageReference": "[variables('osType')]" + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('virtualNetworkName')]", + "location": "[parameters('region')]", + "apiVersion": "2019-06-01", + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "addressPrefix": "[variables('subnetPrefix')]" + } + } + ] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "name": "[variables('publicIPAddressName')]", + "location": "[parameters('region')]", + "apiVersion": "2019-06-01", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "properties": { + "publicIPAllocationMethod": "Dynamic", + "dnsSettings": { + "domainNameLabel": "[variables('namingInfix')]" + } + } + }, + { + "type": "Microsoft.Network/loadBalancers", + "name": "[variables('loadBalancerName')]", + "location": "[parameters('region')]", + "apiVersion": "2020-03-01", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerFrontEnd", + "properties": { + "publicIPAddress": { + "id": "[variables('publicIPAddressID')]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "[variables('bePoolName')]" + } + ], + "inboundNatPools": [ + { + "name": "[variables('natPoolName')]", + "properties": { + "frontendIPConfiguration": { + "id": "[variables('frontEndIPConfigID')]" + }, + "protocol": "Tcp", + "frontendPortRangeStart": "[variables('natStartPort')]", + "frontendPortRangeEnd": "[variables('natEndPort')]", + "backendPort": "[variables('natBackendPort')]" + } + } + ] + } + }, + { + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "fail2", + "location": "[parameters('region')]", + "apiVersion": "2020-06-01", + "dependsOn": [ + "[concat('Microsoft.Network/loadBalancers/', variables('loadBalancerName'))]", + "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]" + ], + "sku": { + "name": "[parameters('vmSize')]", + "tier": "Standard", + "capacity": "[parameters('instanceCount')]" + }, + "properties": { + "overprovision": "true", + "upgradePolicy": { + "mode": "Manual" + }, + "virtualMachineProfile": { + "storageProfile": { + "osDisk": { + "createOption": "FromImage", + "caching": "ReadWrite", + "managedDisk": { + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + }, + "storageAccountType": "Premium_LRS" + } + }, + "dataDisks": [ + { + "lun": 0, + "createOption": "Empty", + "caching": "None", + "managedDisk": { + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + }, + "storageAccountType": "Premium_LRS" + }, + "diskSizeGB": 64 + } + ], + "imageReference": "[variables('imageReference')]" + }, + "osProfile": { + "computerNamePrefix": "[variables('namingInfix')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[variables('nicName')]", + "properties": { + "primary": true, + "ipConfigurations": [ + { + "name": "[variables('ipConfigName')]", + "properties": { + "subnet": { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'), '/subnets/', variables('subnetName'))]" + }, + "loadBalancerBackendAddressPools": [ + { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/backendAddressPools/', variables('bePoolName'))]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/inboundNatPools/', variables('natPoolName'))]" + } + ] + } + } + ] + } + } + ] + } + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-pass.json b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-pass.json new file mode 100644 index 00000000000..a00f8e0ebdd --- /dev/null +++ b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/scaleset-pass.json @@ -0,0 +1,252 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmSize": { + "type": "string", + "defaultValue": "Standard_DS3_V2", + "metadata": { + "description": "Size of VMs in the VM Scale Set." + } + }, + "windowsOSVersion": { + "type": "string", + "defaultValue": "2012-R2-Datacenter", + "allowedValues": [ + "2008-R2-SP1", + "2012-Datacenter", + "2012-R2-Datacenter" + ], + "metadata": { + "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter." + } + }, + "vmssName": { + "type": "string", + "maxLength": 9 + }, + "instanceCount": { + "type": "int", + "defaultValue": 2, + "metadata": { + "description": "Number of VM instances (100 or less)." + }, + "maxValue": 100 + }, + "adminUsername": { + "type": "string", + "defaultValue": "adminUserIsTest", + "metadata": { + "description": "Admin username on all VMs." + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Admin password on all VMs." + } + } + , + "diskEncryptionSetId": { + "type": "string", + "defaultValue": "" + }, + "region": { + "type": "string", + "defaultValue": "CentralUSEUAP" + } + }, + "variables": { + "namingInfix": "[toLower(parameters('vmssName'))]", + "addressPrefix": "10.0.0.0/16", + "subnetPrefix": "10.0.0.0/24", + "virtualNetworkName": "[concat(variables('namingInfix'), 'vnet')]", + "publicIPAddressName": "[concat(variables('namingInfix'), 'pip')]", + "subnetName": "[concat(variables('namingInfix'), 'subnet')]", + "loadBalancerName": "[concat(variables('namingInfix'), 'lb')]", + "publicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]", + "lbID": "[resourceId('Microsoft.Network/loadBalancers',variables('loadBalancerName'))]", + "natPoolName": "[concat(variables('namingInfix'), 'natpool')]", + "bePoolName": "[concat(variables('namingInfix'), 'bepool')]", + "natStartPort": 50000, + "natEndPort": 50119, + "natBackendPort": 3389, + "nicName": "[concat(variables('namingInfix'), 'nic')]", + "ipConfigName": "[concat(variables('namingInfix'), 'ipconfig')]", + "frontEndIPConfigID": "[concat(variables('lbID'),'/frontendIPConfigurations/loadBalancerFrontEnd')]", + "osType": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "[parameters('windowsOSVersion')]", + "version": "latest" + }, + "imageReference": "[variables('osType')]" + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('virtualNetworkName')]", + "location": "[parameters('region')]", + "apiVersion": "2019-06-01", + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "addressPrefix": "[variables('subnetPrefix')]" + } + } + ] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "name": "[variables('publicIPAddressName')]", + "location": "[parameters('region')]", + "apiVersion": "2019-06-01", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "properties": { + "publicIPAllocationMethod": "Dynamic", + "dnsSettings": { + "domainNameLabel": "[variables('namingInfix')]" + } + } + }, + { + "type": "Microsoft.Network/loadBalancers", + "name": "[variables('loadBalancerName')]", + "location": "[parameters('region')]", + "apiVersion": "2020-03-01", + "dependsOn": [ + "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]" + ], + "properties": { + "frontendIPConfigurations": [ + { + "name": "LoadBalancerFrontEnd", + "properties": { + "publicIPAddress": { + "id": "[variables('publicIPAddressID')]" + } + } + } + ], + "backendAddressPools": [ + { + "name": "[variables('bePoolName')]" + } + ], + "inboundNatPools": [ + { + "name": "[variables('natPoolName')]", + "properties": { + "frontendIPConfiguration": { + "id": "[variables('frontEndIPConfigID')]" + }, + "protocol": "Tcp", + "frontendPortRangeStart": "[variables('natStartPort')]", + "frontendPortRangeEnd": "[variables('natEndPort')]", + "backendPort": "[variables('natBackendPort')]" + } + } + ] + } + }, + { + "type": "Microsoft.Compute/virtualMachineScaleSets", + "name": "pass", + "location": "[parameters('region')]", + "apiVersion": "2020-06-01", + "dependsOn": [ + "[concat('Microsoft.Network/loadBalancers/', variables('loadBalancerName'))]", + "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]" + ], + "sku": { + "name": "[parameters('vmSize')]", + "tier": "Standard", + "capacity": "[parameters('instanceCount')]" + }, + "properties": { + "overprovision": "true", + "upgradePolicy": { + "mode": "Manual" + }, + "virtualMachineProfile": { + "storageProfile": { + "osDisk": { + "createOption": "FromImage", + "caching": "ReadWrite", + "managedDisk": { + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + }, + "storageAccountType": "Premium_LRS" + } + }, + "dataDisks": [ + { + "lun": 0, + "createOption": "Empty", + "caching": "None", + "managedDisk": { + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + }, + "storageAccountType": "Premium_LRS" + }, + "diskSizeGB": 64 + } + ], + "imageReference": "[variables('imageReference')]" + }, + "securityProfile":{ + "encryptionAtHost": "true" + }, + "osProfile": { + "computerNamePrefix": "[variables('namingInfix')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[variables('nicName')]", + "properties": { + "primary": true, + "ipConfigurations": [ + { + "name": "[variables('ipConfigName')]", + "properties": { + "subnet": { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'), '/subnets/', variables('subnetName'))]" + }, + "loadBalancerBackendAddressPools": [ + { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/backendAddressPools/', variables('bePoolName'))]" + } + ], + "loadBalancerInboundNatPools": [ + { + "id": "[concat('/subscriptions/', subscription().subscriptionId,'/resourceGroups/', resourceGroup().name, '/providers/Microsoft.Network/loadBalancers/', variables('loadBalancerName'), '/inboundNatPools/', variables('natPoolName'))]" + } + ] + } + } + ] + } + } + ] + } + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail.json b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail.json new file mode 100644 index 00000000000..76e1c7ed7bb --- /dev/null +++ b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail.json @@ -0,0 +1,161 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "virtualMachineName": { + "type": "string", + "defaultValue": "" + }, + "adminPassword": { + "type": "securestring", + "defaultValue": "" + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_DS3_V2" + }, + "diskEncryptionSetId": { + "type": "string", + "defaultValue": "" + }, + "region": { + "type": "string", + "defaultValue": "CentralUSEUAP" + } + }, + "variables": { + "diskName": "[concat(parameters('virtualMachineName'), '_osDisk')]", + "dataDiskName": "[concat(parameters('virtualMachineName'), '_dataDisk1')]", + "networkInterfaceName": "[toLower(parameters('virtualMachineName'))]", + "publicIpAddressName": "[concat(toLower(parameters('virtualMachineName')),'_ip')]", + "vnetName": "[concat(toLower(parameters('virtualMachineName')),'_vnet')]", + "subnetName": "[concat(toLower(parameters('virtualMachineName')),'_subnet')]", + "imageReference": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2019-Datacenter", + "version": "latest" + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('vnetName')]", + "apiVersion": "2019-06-01", + "location": "[parameters('region')]", + "scale": null, + "properties": { + "addressSpace": { + "addressPrefixes": [ + "10.2.3.0/24" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "provisioningState": "Succeeded", + "addressPrefix": "10.2.3.0/24" + } + } + ] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "name": "[variables('publicIpAddressName')]", + "apiVersion": "2019-06-01", + "location": "[parameters('region')]", + "scale": null, + "properties": { + "publicIPAllocationMethod": "Dynamic" + } + }, + { + "apiVersion": "2019-06-01", + "type": "Microsoft.Network/networkInterfaces", + "name": "[variables('networkInterfaceName')]", + "location": "[parameters('region')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]" + }, + "subnet": { + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('subnetName'))]" + } + } + } + ] + } + }, + { + "name": "fail", + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2020-06-01", + "location": "[parameters('region')]", + "dependsOn": [ + "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]" + ], + "properties": { + "osProfile": { + "computerName": "[parameters('virtualMachineName')]", + "adminUsername": "adminUserIsTest", + "adminPassword": "[parameters('adminPassword')]" + }, + "securityProfile":{ + "encryptionAtHost": "false" + }, + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "storageProfile": { + "imageReference": "[variables('imageReference')]", + "osDisk": { + "name": "[variables('diskName')]", + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + } + } + }, + "dataDisks": [ + { + "name": "[variables('dataDiskName')]", + "diskSizeGB": "128", + "lun": "0", + "createOption": "Empty", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + } + } + } + ] + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]" + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail2.json b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail2.json new file mode 100644 index 00000000000..14c7f7e8f44 --- /dev/null +++ b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-fail2.json @@ -0,0 +1,158 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "virtualMachineName": { + "type": "string", + "defaultValue": "" + }, + "adminPassword": { + "type": "securestring", + "defaultValue": "" + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_DS3_V2" + }, + "diskEncryptionSetId": { + "type": "string", + "defaultValue": "" + }, + "region": { + "type": "string", + "defaultValue": "CentralUSEUAP" + } + }, + "variables": { + "diskName": "[concat(parameters('virtualMachineName'), '_osDisk')]", + "dataDiskName": "[concat(parameters('virtualMachineName'), '_dataDisk1')]", + "networkInterfaceName": "[toLower(parameters('virtualMachineName'))]", + "publicIpAddressName": "[concat(toLower(parameters('virtualMachineName')),'_ip')]", + "vnetName": "[concat(toLower(parameters('virtualMachineName')),'_vnet')]", + "subnetName": "[concat(toLower(parameters('virtualMachineName')),'_subnet')]", + "imageReference": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2019-Datacenter", + "version": "latest" + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('vnetName')]", + "apiVersion": "2019-06-01", + "location": "[parameters('region')]", + "scale": null, + "properties": { + "addressSpace": { + "addressPrefixes": [ + "10.2.3.0/24" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "provisioningState": "Succeeded", + "addressPrefix": "10.2.3.0/24" + } + } + ] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "name": "[variables('publicIpAddressName')]", + "apiVersion": "2019-06-01", + "location": "[parameters('region')]", + "scale": null, + "properties": { + "publicIPAllocationMethod": "Dynamic" + } + }, + { + "apiVersion": "2019-06-01", + "type": "Microsoft.Network/networkInterfaces", + "name": "[variables('networkInterfaceName')]", + "location": "[parameters('region')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]" + }, + "subnet": { + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('subnetName'))]" + } + } + } + ] + } + }, + { + "name": "fail2", + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2020-06-01", + "location": "[parameters('region')]", + "dependsOn": [ + "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]" + ], + "properties": { + "osProfile": { + "computerName": "[parameters('virtualMachineName')]", + "adminUsername": "adminUserIsTest", + "adminPassword": "[parameters('adminPassword')]" + }, + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "storageProfile": { + "imageReference": "[variables('imageReference')]", + "osDisk": { + "name": "[variables('diskName')]", + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + } + } + }, + "dataDisks": [ + { + "name": "[variables('dataDiskName')]", + "diskSizeGB": "128", + "lun": "0", + "createOption": "Empty", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + } + } + } + ] + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]" + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-pass.json b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-pass.json new file mode 100644 index 00000000000..20a48d841c4 --- /dev/null +++ b/tests/arm/checks/resource/example_VMEncryptionAtHostEnabled/vm-pass.json @@ -0,0 +1,161 @@ +{ + "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "virtualMachineName": { + "type": "string", + "defaultValue": "" + }, + "adminPassword": { + "type": "securestring", + "defaultValue": "" + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_DS3_V2" + }, + "diskEncryptionSetId": { + "type": "string", + "defaultValue": "" + }, + "region": { + "type": "string", + "defaultValue": "CentralUSEUAP" + } + }, + "variables": { + "diskName": "[concat(parameters('virtualMachineName'), '_osDisk')]", + "dataDiskName": "[concat(parameters('virtualMachineName'), '_dataDisk1')]", + "networkInterfaceName": "[toLower(parameters('virtualMachineName'))]", + "publicIpAddressName": "[concat(toLower(parameters('virtualMachineName')),'_ip')]", + "vnetName": "[concat(toLower(parameters('virtualMachineName')),'_vnet')]", + "subnetName": "[concat(toLower(parameters('virtualMachineName')),'_subnet')]", + "imageReference": { + "publisher": "MicrosoftWindowsServer", + "offer": "WindowsServer", + "sku": "2019-Datacenter", + "version": "latest" + } + }, + "resources": [ + { + "type": "Microsoft.Network/virtualNetworks", + "name": "[variables('vnetName')]", + "apiVersion": "2019-06-01", + "location": "[parameters('region')]", + "scale": null, + "properties": { + "addressSpace": { + "addressPrefixes": [ + "10.2.3.0/24" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "provisioningState": "Succeeded", + "addressPrefix": "10.2.3.0/24" + } + } + ] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "name": "[variables('publicIpAddressName')]", + "apiVersion": "2019-06-01", + "location": "[parameters('region')]", + "scale": null, + "properties": { + "publicIPAllocationMethod": "Dynamic" + } + }, + { + "apiVersion": "2019-06-01", + "type": "Microsoft.Network/networkInterfaces", + "name": "[variables('networkInterfaceName')]", + "location": "[parameters('region')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('vnetName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIpAddressName'))]" + }, + "subnet": { + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('vnetName'), variables('subnetName'))]" + } + } + } + ] + } + }, + { + "name": "pass", + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2020-06-01", + "location": "[parameters('region')]", + "dependsOn": [ + "[concat('Microsoft.Network/networkInterfaces/', variables('networkInterfaceName'))]" + ], + "properties": { + "osProfile": { + "computerName": "[parameters('virtualMachineName')]", + "adminUsername": "adminUserIsTest", + "adminPassword": "[parameters('adminPassword')]" + }, + "securityProfile":{ + "encryptionAtHost": "true" + }, + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "storageProfile": { + "imageReference": "[variables('imageReference')]", + "osDisk": { + "name": "[variables('diskName')]", + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + } + } + }, + "dataDisks": [ + { + "name": "[variables('dataDiskName')]", + "diskSizeGB": "128", + "lun": "0", + "createOption": "Empty", + "managedDisk": { + "storageAccountType": "Premium_LRS", + "diskEncryptionSet": { + "id": "[parameters('diskEncryptionSetId')]" + } + } + } + ] + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]" + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/checks/resource/test_VMEncryptionAtHostEnabled.py b/tests/arm/checks/resource/test_VMEncryptionAtHostEnabled.py new file mode 100644 index 00000000000..4283cb59d0f --- /dev/null +++ b/tests/arm/checks/resource/test_VMEncryptionAtHostEnabled.py @@ -0,0 +1,44 @@ +import unittest +from pathlib import Path + +from checkov.arm.checks.resource.VMEncryptionAtHostEnabled import check +from checkov.arm.runner import Runner +from checkov.runner_filter import RunnerFilter + + +class TestVMEncryptionAtHostEnabled(unittest.TestCase): + def test_summary(self): + # given + test_files_dir = Path(__file__).parent / "example_VMEncryptionAtHostEnabled" + + # when + report = Runner().run(root_folder=str(test_files_dir), runner_filter=RunnerFilter(checks=[check.id])) + + # then + summary = report.get_summary() + + passing_resources = { + "Microsoft.Compute/virtualMachines.pass", + "Microsoft.Compute/virtualMachineScaleSets.pass" + } + failing_resources = { + "Microsoft.Compute/virtualMachines.fail", + "Microsoft.Compute/virtualMachines.fail2", + "Microsoft.Compute/virtualMachineScaleSets.fail", + "Microsoft.Compute/virtualMachineScaleSets.fail2" + } + + passed_check_resources = {c.resource for c in report.passed_checks} + failed_check_resources = {c.resource for c in report.failed_checks} + + self.assertEqual(summary["passed"], len(passing_resources)) + self.assertEqual(summary["failed"], len(failing_resources)) + self.assertEqual(summary["skipped"], 0) + self.assertEqual(summary["parsing_errors"], 0) + + self.assertEqual(passing_resources, passed_check_resources) + self.assertEqual(failing_resources, failed_check_resources) + + +if __name__ == "__main__": + unittest.main()