diff --git a/arm/Microsoft.Compute/virtualMachines/deploy.bicep b/arm/Microsoft.Compute/virtualMachines/deploy.bicep index e6269f9976..f1b2363cf7 100644 --- a/arm/Microsoft.Compute/virtualMachines/deploy.bicep +++ b/arm/Microsoft.Compute/virtualMachines/deploy.bicep @@ -3,6 +3,11 @@ param name string = take(toLower(uniqueString(resourceGroup().name)), 10) @description('Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are \'none\' (Default), \'uppercase\' and \'lowercase\'.') +@allowed([ + 'none' + 'uppercase' + 'lowercase' +]) param vmComputerNamesTransformation string = 'none' @description('Required. Specifies the size for the VMs') diff --git a/arm/Microsoft.Compute/virtualMachines/readme.md b/arm/Microsoft.Compute/virtualMachines/readme.md index ac25bd60c8..d380ae0cd6 100644 --- a/arm/Microsoft.Compute/virtualMachines/readme.md +++ b/arm/Microsoft.Compute/virtualMachines/readme.md @@ -97,7 +97,7 @@ This module deploys one Virtual Machine with one or multiple nics and optionally | `timeZone` | string | `''` | | Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | | `ultraSSDEnabled` | bool | `False` | | The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | | `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | -| `vmComputerNamesTransformation` | string | `'none'` | | Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'. | +| `vmComputerNamesTransformation` | string | `'none'` | `[none, uppercase, lowercase]` | Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'. | | `vmPriority` | string | `'Regular'` | `[Regular, Low, Spot]` | Specifies the priority for the virtual machine. | | `vTpmEnabled` | bool | `False` | | Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | | `winRM` | object | `{object}` | | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | diff --git a/constructs/Microsoft.Compute/virtualMachinesMultiple/.parameters/linux.prefix.parameter.json b/constructs/Microsoft.Compute/virtualMachinesMultiple/.parameters/linux.prefix.parameter.json new file mode 100644 index 0000000000..2842a912e2 --- /dev/null +++ b/constructs/Microsoft.Compute/virtualMachinesMultiple/.parameters/linux.prefix.parameter.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmInitialNumber": { + "value": 1 + }, + "vmNamePrefix": { + "value": "<>-vm-linux-prefix" + }, + "vmNumberOfInstances": { + "value": 3 + }, + "osType": { + "value": "Linux" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + } + } + ] + } + ] + } + } +} diff --git a/constructs/Microsoft.Compute/virtualMachinesMultiple/.parameters/linux.vmnames.parameter.json b/constructs/Microsoft.Compute/virtualMachinesMultiple/.parameters/linux.vmnames.parameter.json new file mode 100644 index 0000000000..c026d03d1d --- /dev/null +++ b/constructs/Microsoft.Compute/virtualMachinesMultiple/.parameters/linux.vmnames.parameter.json @@ -0,0 +1,65 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "vmNames": { + "value": [ + "<>-vm-linux-vmnames-01", + "<>-vm-linux-vmnames-02", + "<>-vm-linux-vmnames-03" + ] + }, + "osType": { + "value": "Linux" + }, + "imageReference": { + "value": { + "publisher": "Canonical", + "offer": "UbuntuServer", + "sku": "18.04-LTS", + "version": "latest" + } + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "vmSize": { + "value": "Standard_B12ms" + }, + "adminUsername": { + "value": "localAdminUser" + }, + "disablePasswordAuthentication": { + "value": true + }, + "publicKeys": { + "value": [ + { + "path": "/home/localAdminUser/.ssh/authorized_keys", + "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" + } + ] + }, + "nicConfigurations": { + "value": [ + { + "nicSuffix": "-nic-01", + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + } + } + ] + } + ] + } + } +} diff --git a/constructs/Microsoft.Compute/virtualMachinesMultiple/deploy.bicep b/constructs/Microsoft.Compute/virtualMachinesMultiple/deploy.bicep new file mode 100644 index 0000000000..c6109a9d87 --- /dev/null +++ b/constructs/Microsoft.Compute/virtualMachinesMultiple/deploy.bicep @@ -0,0 +1,388 @@ +@description('Conditional. Name(s) of the virtual machine(s). If no explicit names are provided, VM name(s) will be generated based on the vmNamePrefix, vmNumberOfInstances and vmInitialNumber parameters.') +param vmNames array = [] + +@description('Conditional. If no explicit values were provided in the vmNames parameter, this prefix will be used in combination with the vmNumberOfInstances and the vmInitialNumber parameters to create unique VM names. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group\'s name.') +param vmNamePrefix string = take(toLower(uniqueString(resourceGroup().name)), 10) + +@description('Conditional. If no explicit values were provided in the vmNames parameter, this parameter will be used to generate VM names, using the vmNamePrefix and the vmNumberOfInstances values.') +param vmInitialNumber int = 1 + +@description('Conditional. If no explicit values were provided in the vmNames parameter, this parameter will be used to generate VM names, using the vmNamePrefix and the vmInitialNumber values.') +@minValue(1) +@maxValue(800) +param vmNumberOfInstances int = 1 + +@description('Optional. Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are \'none\' (Default), \'uppercase\' and \'lowercase\'.') +@allowed([ + 'none' + 'uppercase' + 'lowercase' +]) +param vmComputerNamesTransformation string = 'none' + +@description('Required. Specifies the size for the VMs') +param vmSize string + +@description('Optional. This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param encryptionAtHost bool = true + +@description('Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings.') +param securityType string = '' + +@description('Optional. Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param secureBootEnabled bool = false + +@description('Optional. Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings.') +param vTpmEnabled bool = false + +@description('Required. OS image reference. In case of marketplace images, it\'s the combination of the publisher, offer, sku, version attributes. In case of custom images it\'s the resource ID of the custom image.') +param imageReference object + +@description('Optional. Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use.') +param plan object = {} + +@description('Required. Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param osDisk object + +@description('Optional. Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs.') +param dataDisks array = [] + +@description('Optional. The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled.') +param ultraSSDEnabled bool = false + +@description('Required. Administrator username') +@secure() +param adminUsername string + +@description('Optional. When specifying a Windows Virtual Machine, this value should be passed') +@secure() +param adminPassword string = '' + +@description('Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format.') +param customData string = '' + +@description('Optional. Specifies set of certificates that should be installed onto the virtual machine.') +param certificatesToBeInstalled array = [] + +@description('Optional. Specifies the priority for the virtual machine.') +@allowed([ + 'Regular' + 'Low' + 'Spot' +]) +param vmPriority string = 'Regular' + +@description('Optional. Specifies the eviction policy for the low priority virtual machine. Will result in \'Deallocate\' eviction policy.') +param enableEvictionPolicy bool = false + +@description('Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars.') +param maxPriceForLowPriorityVm string = '' + +@description('Optional. Specifies resource ID about the dedicated host that the virtual machine resides in.') +param dedicatedHostId string = '' + +@description('Optional. Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system.') +@allowed([ + 'Windows_Client' + 'Windows_Server' + '' +]) +param licenseType string = '' + +@description('Optional. The list of SSH public keys used to authenticate with linux based VMs') +param publicKeys array = [] + +@description('Optional. Enables system assigned managed identity on the resource.') +param systemAssignedIdentity bool = false + +@description('Optional. The ID(s) to assign to the resource.') +param userAssignedIdentities object = {} + +@description('Optional. Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Resource name of a proximity placement group.') +param proximityPlacementGroupName string = '' + +@description('Optional. Resource name of an availability set. Cannot be used in combination with availability zone nor scale set.') +param availabilitySetName string = '' + +@description('Optional. If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set.') +@allowed([ + 0 + 1 + 2 + 3 +]) +param availabilityZone int = 0 + +// External resources +@description('Required. Configures NICs and PIPs.') +param nicConfigurations array + +@description('Optional. The name of the PIP diagnostic setting, if deployed.') +param pipDiagnosticSettingsName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +]) +param pipdiagnosticLogCategoriesToEnable array = [ + 'DDoSProtectionNotifications' + 'DDoSMitigationFlowLogs' + 'DDoSMitigationReports' +] + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param pipdiagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the NIC diagnostic setting, if deployed.') +param nicDiagnosticSettingsName string = '' + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param nicdiagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. Recovery service vault name to add VMs to backup.') +param backupVaultName string = '' + +@description('Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default.') +param backupVaultResourceGroup string = resourceGroup().name + +@description('Optional. Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault.') +param backupPolicyName string = 'DefaultPolicy' + +@description('Optional. Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key.') +param enableServerSideEncryption bool = false + +// Child resources +@description('Optional. Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine.') +param allowExtensionOperations bool = true + +@description('Optional. Required if domainName is specified. Password of the user specified in domainJoinUser parameter') +@secure() +param extensionDomainJoinPassword string = '' + +@description('Optional. The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDomainJoinConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionAntiMalwareConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionMonitoringAgentConfig object = { + enabled: false +} + +@description('Optional. Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true.') +param monitoringWorkspaceId string = '' + +@description('Optional. The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDependencyAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionNetworkWatcherAgentConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDiskEncryptionConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionDSCConfig object = { + enabled: false +} + +@description('Optional. The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed') +param extensionCustomScriptConfig object = { + enabled: false + fileData: [] +} + +@description('Optional. Any object that contains the extension specific protected settings') +@secure() +param extensionCustomScriptProtectedSetting object = {} + +// Shared parameters +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +@minValue(0) +@maxValue(365) +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. Resource ID of the diagnostic storage account.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace.') +param diagnosticWorkspaceId string = '' + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category.') +param diagnosticEventHubName string = '' + +@allowed([ + 'CanNotDelete' + 'NotSpecified' + 'ReadOnly' +]) +@description('Optional. Specify the type of lock.') +param lock string = 'NotSpecified' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'') +param roleAssignments array = [] + +@description('Optional. Tags of the resource.') +param tags object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Do not provide a value! This date value is used to generate a registration token.') +param baseTime string = utcNow('u') + +@description('Optional. SAS token validity length to use to download files from storage accounts. Usage: \'PT8H\' - valid for 8 hours; \'P5D\' - valid for 5 days; \'P1Y\' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours.') +param sasTokenValidityLength string = 'PT8H' + +@description('Required. The chosen OS type') +@allowed([ + 'Windows' + 'Linux' +]) +param osType string + +@description('Optional. Specifies whether password authentication should be disabled.') +param disablePasswordAuthentication bool = false + +@description('Optional. Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later.') +param provisionVMAgent bool = true + +@description('Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. Specifies the time zone of the virtual machine. e.g. \'Pacific Standard Time\'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones.') +param timeZone string = '' + +@description('Optional. Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM object = {} + +@description('Optional. Any VM configuration profile assignments') +param configurationProfileAssignments array = [] + +var vmGeneratedNames = [for instance in range(0, vmNumberOfInstances): '${vmNamePrefix}${padLeft((instance + vmInitialNumber), 3, '0')}'] + +var vmNamesToApply = !empty(vmNames) ? vmNames : vmGeneratedNames + +module virtualMachine '../../../arm/Microsoft.Compute/virtualMachines/deploy.bicep' = [for (vmName, index) in vmNamesToApply: { + name: '${deployment().name}-vm-${index}' + params: { + name: vmName + nicConfigurations: nicConfigurations + adminUsername: adminUsername + adminPassword: adminPassword + osDisk: osDisk + imageReference: imageReference + osType: osType + vmSize: vmSize + additionalUnattendContent: additionalUnattendContent + allowExtensionOperations: allowExtensionOperations + availabilitySetName: availabilitySetName + backupPolicyName: backupPolicyName + backupVaultName: backupVaultName + backupVaultResourceGroup: backupVaultResourceGroup + baseTime: baseTime + bootDiagnosticStorageAccountName: bootDiagnosticStorageAccountName + bootDiagnosticStorageAccountUri: bootDiagnosticStorageAccountUri + certificatesToBeInstalled: certificatesToBeInstalled + configurationProfileAssignments: configurationProfileAssignments + customData: customData + dataDisks: dataDisks + dedicatedHostId: dedicatedHostId + diagnosticEventHubAuthorizationRuleId: diagnosticEventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticEventHubName + diagnosticLogsRetentionInDays: diagnosticLogsRetentionInDays + diagnosticStorageAccountId: diagnosticStorageAccountId + diagnosticWorkspaceId: diagnosticWorkspaceId + disablePasswordAuthentication: disablePasswordAuthentication + enableAutomaticUpdates: enableAutomaticUpdates + enableDefaultTelemetry: enableDefaultTelemetry + enableEvictionPolicy: enableEvictionPolicy + enableServerSideEncryption: enableServerSideEncryption + encryptionAtHost: encryptionAtHost + extensionAntiMalwareConfig: extensionAntiMalwareConfig + extensionCustomScriptConfig: extensionCustomScriptConfig + extensionCustomScriptProtectedSetting: extensionCustomScriptProtectedSetting + extensionDependencyAgentConfig: extensionDependencyAgentConfig + extensionDiskEncryptionConfig: extensionDiskEncryptionConfig + extensionDomainJoinConfig: extensionDomainJoinConfig + extensionDomainJoinPassword: extensionDomainJoinPassword + extensionDSCConfig: extensionDSCConfig + extensionMonitoringAgentConfig: extensionMonitoringAgentConfig + extensionNetworkWatcherAgentConfig: extensionNetworkWatcherAgentConfig + licenseType: licenseType + location: location + lock: lock + maxPriceForLowPriorityVm: maxPriceForLowPriorityVm + monitoringWorkspaceId: monitoringWorkspaceId + nicdiagnosticMetricsToEnable: nicdiagnosticMetricsToEnable + nicDiagnosticSettingsName: !empty(nicDiagnosticSettingsName) ? nicDiagnosticSettingsName : '${vmName}-diagnosticSettings' + pipdiagnosticLogCategoriesToEnable: pipdiagnosticLogCategoriesToEnable + pipdiagnosticMetricsToEnable: pipdiagnosticMetricsToEnable + pipDiagnosticSettingsName: !empty(pipDiagnosticSettingsName) ? pipDiagnosticSettingsName : '${vmName}-diagnosticSettings' + plan: plan + provisionVMAgent: provisionVMAgent + proximityPlacementGroupName: proximityPlacementGroupName + publicKeys: publicKeys + roleAssignments: roleAssignments + sasTokenValidityLength: sasTokenValidityLength + secureBootEnabled: secureBootEnabled + securityType: securityType + systemAssignedIdentity: systemAssignedIdentity + tags: tags + timeZone: timeZone + ultraSSDEnabled: ultraSSDEnabled + userAssignedIdentities: userAssignedIdentities + vmComputerNamesTransformation: vmComputerNamesTransformation + vmPriority: vmPriority + vTpmEnabled: vTpmEnabled + winRM: winRM + availabilityZone: availabilityZone + } +}] + +@description('The resource ID(s) of the VM(s).') +output virtualMachinesResourceId array = [for vmIndex in range(0, length(vmNamesToApply)): virtualMachine[vmIndex].outputs.resourceId] + +@description('The name of the resource group the VM(s) was/were created in.') +output virtualMachinesResourceGroup string = resourceGroup().name + +@description('The names of the VMs.') +output virtualMachinesName array = [for vmIndex in range(0, length(vmNamesToApply)): virtualMachine[vmIndex].outputs.name] diff --git a/constructs/Microsoft.Compute/virtualMachinesMultiple/readme.md b/constructs/Microsoft.Compute/virtualMachinesMultiple/readme.md new file mode 100644 index 0000000000..f5b73be22f --- /dev/null +++ b/constructs/Microsoft.Compute/virtualMachinesMultiple/readme.md @@ -0,0 +1,194 @@ +# Multiple Virtual Machines `[Microsoft.Compute/virtualMachines]` + +This module deploys one or multiple Virtual Machines. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2017-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2020-10-01-preview](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-10-01-preview/roleAssignments) | +| `Microsoft.Automanage/configurationProfileAssignments` | [2021-04-30-preview](https://docs.microsoft.com/en-us/azure/templates) | +| `Microsoft.Compute/virtualMachines` | [2021-07-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines) | +| `Microsoft.Compute/virtualMachines/extensions` | [2021-07-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-07-01/virtualMachines/extensions) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | +| `Microsoft.Network/networkInterfaces` | [2021-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/networkInterfaces) | +| `Microsoft.Network/publicIPAddresses` | [2021-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Network/2021-05-01/publicIPAddresses) | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | [2021-06-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2021-06-01/vaults/backupFabrics/protectionContainers/protectedItems) | + +## Parameters + +**Required parameters** +| Parameter Name | Type | Allowed Values | Description | +| :-- | :-- | :-- | :-- | +| `adminUsername` | secureString | | Administrator username | +| `imageReference` | object | | OS image reference. In case of marketplace images, it's the combination of the publisher, offer, sku, version attributes. In case of custom images it's the resource ID of the custom image. | +| `nicConfigurations` | array | | Configures NICs and PIPs. | +| `osDisk` | object | | Specifies the OS disk. For security reasons, it is recommended to specify DiskEncryptionSet into the osDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `osType` | string | `[Windows, Linux]` | The chosen OS type | +| `vmSize` | string | | Specifies the size for the VMs | + +**Conditional parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `vmInitialNumber` | int | `1` | If no explicit values were provided in the vmNames parameter, this parameter will be used to generate VM names, using the vmNamePrefix and the vmNumberOfInstances values. | +| `vmNamePrefix` | string | `[take(toLower(uniqueString(resourceGroup().name)), 10)]` | If no explicit values were provided in the vmNames parameter, this prefix will be used in combination with the vmNumberOfInstances and the vmInitialNumber parameters to create unique VM names. You should use a unique prefix to reduce name collisions in Active Directory. If no value is provided, a 10 character long unique string will be generated based on the Resource Group's name. | +| `vmNames` | array | `[]` | Name(s) of the virtual machine(s). If no explicit names are provided, VM name(s) will be generated based on the vmNamePrefix, vmNumberOfInstances and vmInitialNumber parameters. | +| `vmNumberOfInstances` | int | `1` | If no explicit values were provided in the vmNames parameter, this parameter will be used to generate VM names, using the vmNamePrefix and the vmInitialNumber values. | + +**Optional parameters** +| Parameter Name | Type | Default Value | Allowed Values | Description | +| :-- | :-- | :-- | :-- | :-- | +| `additionalUnattendContent` | array | `[]` | | Specifies additional base-64 encoded XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. - AdditionalUnattendContent object | +| `adminPassword` | secureString | `''` | | When specifying a Windows Virtual Machine, this value should be passed | +| `allowExtensionOperations` | bool | `True` | | Specifies whether extension operations should be allowed on the virtual machine. This may only be set to False when no extensions are present on the virtual machine. | +| `availabilitySetName` | string | `''` | | Resource name of an availability set. Cannot be used in combination with availability zone nor scale set. | +| `availabilityZone` | int | `0` | `[0, 1, 2, 3]` | If set to 1, 2 or 3, the availability zone for all VMs is hardcoded to that value. If zero, then availability zones is not used. Cannot be used in combination with availability set nor scale set. | +| `backupPolicyName` | string | `'DefaultPolicy'` | | Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. | +| `backupVaultName` | string | `''` | | Recovery service vault name to add VMs to backup. | +| `backupVaultResourceGroup` | string | `[resourceGroup().name]` | | Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. | +| `bootDiagnosticStorageAccountName` | string | `''` | | Storage account used to store boot diagnostic information. Boot diagnostics will be disabled if no value is provided. | +| `bootDiagnosticStorageAccountUri` | string | `[format('.blob.{0}/', environment().suffixes.storage)]` | | Storage account boot diagnostic base URI. | +| `certificatesToBeInstalled` | array | `[]` | | Specifies set of certificates that should be installed onto the virtual machine. | +| `configurationProfileAssignments` | array | `[]` | | Any VM configuration profile assignments | +| `customData` | string | `''` | | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| `dataDisks` | array | `[]` | | Specifies the data disks. For security reasons, it is recommended to specify DiskEncryptionSet into the dataDisk object. Restrictions: DiskEncryptionSet cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `dedicatedHostId` | string | `''` | | Specifies resource ID about the dedicated host that the virtual machine resides in. | +| `diagnosticEventHubAuthorizationRuleId` | string | `''` | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | +| `diagnosticEventHubName` | string | `''` | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. | +| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | +| `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | +| `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | +| `disablePasswordAuthentication` | bool | `False` | | Specifies whether password authentication should be disabled. | +| `enableAutomaticUpdates` | bool | `True` | | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `enableEvictionPolicy` | bool | `False` | | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| `enableServerSideEncryption` | bool | `False` | | Specifies if Windows VM disks should be encrypted with Server-side encryption + Customer managed Key. | +| `encryptionAtHost` | bool | `True` | | This property can be used by user in the request to enable or disable the Host Encryption for the virtual machine. This will enable the encryption for all the disks including Resource/Temp disk at host itself. For security reasons, it is recommended to set encryptionAtHost to True. Restrictions: Cannot be enabled if Azure Disk Encryption (guest-VM encryption using bitlocker/DM-Crypt) is enabled on your VMs. | +| `extensionAntiMalwareConfig` | object | `{object}` | | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptConfig` | object | `{object}` | | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionCustomScriptProtectedSetting` | secureObject | `{object}` | | Any object that contains the extension specific protected settings | +| `extensionDependencyAgentConfig` | object | `{object}` | | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDiskEncryptionConfig` | object | `{object}` | | The configuration for the [Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinConfig` | object | `{object}` | | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionDomainJoinPassword` | secureString | `''` | | Required if domainName is specified. Password of the user specified in domainJoinUser parameter | +| `extensionDSCConfig` | object | `{object}` | | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionMonitoringAgentConfig` | object | `{object}` | | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `extensionNetworkWatcherAgentConfig` | object | `{object}` | | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed | +| `licenseType` | string | `''` | `[Windows_Client, Windows_Server, ]` | Specifies that the image or disk that is being used was licensed on-premises. This element is only used for images that contain the Windows Server operating system. | +| `location` | string | `[resourceGroup().location]` | | Location for all resources. | +| `lock` | string | `'NotSpecified'` | `[CanNotDelete, NotSpecified, ReadOnly]` | Specify the type of lock. | +| `maxPriceForLowPriorityVm` | string | `''` | | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| `monitoringWorkspaceId` | string | `''` | | Resource ID of the monitoring log analytics workspace. Must be set when extensionMonitoringAgentConfig is set to true. | +| `nicdiagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `nicDiagnosticSettingsName` | string | `''` | | The name of the NIC diagnostic setting, if deployed. | +| `pipdiagnosticLogCategoriesToEnable` | array | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | `[DDoSProtectionNotifications, DDoSMitigationFlowLogs, DDoSMitigationReports]` | The name of logs that will be streamed. | +| `pipdiagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | +| `pipDiagnosticSettingsName` | string | `''` | | The name of the PIP diagnostic setting, if deployed. | +| `plan` | object | `{object}` | | Specifies information about the marketplace image used to create the virtual machine. This element is only used for marketplace images. Before you can use a marketplace image from an API, you must enable the image for programmatic use. | +| `provisionVMAgent` | bool | `True` | | Indicates whether virtual machine agent should be provisioned on the virtual machine. When this property is not specified in the request body, default behavior is to set it to true. This will ensure that VM Agent is installed on the VM so that extensions can be added to the VM later. | +| `proximityPlacementGroupName` | string | `''` | | Resource name of a proximity placement group. | +| `publicKeys` | array | `[]` | | The list of SSH public keys used to authenticate with linux based VMs | +| `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' | +| `sasTokenValidityLength` | string | `'PT8H'` | | SAS token validity length to use to download files from storage accounts. Usage: 'PT8H' - valid for 8 hours; 'P5D' - valid for 5 days; 'P1Y' - valid for 1 year. When not provided, the SAS token will be valid for 8 hours. | +| `secureBootEnabled` | bool | `False` | | Specifies whether secure boot should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `securityType` | string | `''` | | Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. | +| `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | +| `tags` | object | `{object}` | | Tags of the resource. | +| `timeZone` | string | `''` | | Specifies the time zone of the virtual machine. e.g. 'Pacific Standard Time'. Possible values can be TimeZoneInfo.id value from time zones returned by TimeZoneInfo.GetSystemTimeZones. | +| `ultraSSDEnabled` | bool | `False` | | The flag that enables or disables a capability to have one or more managed data disks with UltraSSD_LRS storage account type on the VM or VMSS. Managed disks with storage account type UltraSSD_LRS can be added to a virtual machine or virtual machine scale set only if this property is enabled. | +| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | +| `vmComputerNamesTransformation` | string | `'none'` | `[none, uppercase, lowercase]` | Specifies whether the computer names should be transformed. The transformation is performed on all computer names. Available transformations are 'none' (Default), 'uppercase' and 'lowercase'. | +| `vmPriority` | string | `'Regular'` | `[Regular, Low, Spot]` | Specifies the priority for the virtual machine. | +| `vTpmEnabled` | bool | `False` | | Specifies whether vTPM should be enabled on the virtual machine. This parameter is part of the UefiSettings. SecurityType should be set to TrustedLaunch to enable UefiSettings. | +| `winRM` | object | `{object}` | | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | + +**Generated parameters** +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `baseTime` | string | `[utcNow('u')]` | Do not provide a value! This date value is used to generate a registration token. | + + +### Parameter Usage: `vmNames` + +Name(s) of the virtual machine(s). If no explicit names are provided, VM name(s) will be generated based on the `vmNamePrefix`, `vmNumberOfInstances` and `vmInitialNumber` parameters. + +```json +"vmNames": { + "value": [ + "<>-vm-linux-vmnames-01", + "<>-vm-linux-vmnames-02", + "<>-vm-linux-vmnames-03" + ] +} +``` + +### Parameter Usage: `roleAssignments` + +Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. + +```json +"roleAssignments": { + "value": [ + { + "roleDefinitionIdOrName": "Reader", + "description": "Reader Role Assignment", + "principalIds": [ + "12345678-1234-1234-1234-123456789012", // object 1 + "78945612-1234-1234-1234-123456789012" // object 2 + ] + }, + { + "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", + "principalIds": [ + "12345678-1234-1234-1234-123456789012" // object 1 + ], + "principalType": "ServicePrincipal" + } + ] +} +``` + +### Parameter Usage: `tags` + +Tag names and tag values can be provided as needed. A tag can be left without a value. + +```json +"tags": { + "value": { + "Environment": "Non-Prod", + "Contact": "test.user@testcompany.com", + "PurchaseOrder": "1234", + "CostCenter": "7890", + "ServiceName": "DeploymentValidation", + "Role": "DeploymentValidation" + } +} +``` + +### Parameter Usage: `userAssignedIdentities` + +You can specify multiple user assigned identities to a resource by providing additional resource IDs using the following format: + +```json +"userAssignedIdentities": { + "value": { + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-001": {}, + "/subscriptions/12345678-1234-1234-1234-123456789012/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-sxx-az-msi-x-002": {} + } +}, +``` + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `virtualMachinesName` | array | The names of the VMs. | +| `virtualMachinesResourceGroup` | string | The name of the resource group the VM(s) was/were created in. | +| `virtualMachinesResourceId` | array | The resource ID(s) of the VM(s). | diff --git a/utilities/tools/Set-ModuleReadMe.ps1 b/utilities/tools/Set-ModuleReadMe.ps1 index 2506d52d7c..f281c471ca 100644 --- a/utilities/tools/Set-ModuleReadMe.ps1 +++ b/utilities/tools/Set-ModuleReadMe.ps1 @@ -523,9 +523,7 @@ function Set-ModuleReadMe { '' '// TODO: Fill in Parameter usage' '', - '## Outputs', - '', - '## Template references' + '## Outputs' ) # New-Item $path $ReadMeFilePath -ItemType 'File' -Force -Value $initialContent $readMeFileContent = $initialContent