From 20ac8b7116cf7781600646dc0d5d85dcdae0df45 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Tue, 7 Nov 2023 22:23:26 +0100 Subject: [PATCH 01/35] Added skeleton --- .../compliance/module.tests.ps1 | 272 ++++++++++++------ 1 file changed, 185 insertions(+), 87 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 700771fe11..c1a0174819 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -3,7 +3,7 @@ param ( [Parameter(Mandatory = $false)] [array] $moduleFolderPaths = ((Get-ChildItem $repoRootPath -Recurse -Directory -Force).FullName | Where-Object { - (Get-ChildItem $_ -File -Depth 0 -Include @('main.json', 'main.bicep') -Force).Count -gt 0 + (Get-ChildItem $_ -File -Depth 0 -Include @('main.bicep') -Force).Count -gt 0 }), [Parameter(Mandatory = $false)] @@ -27,7 +27,6 @@ $script:convertedTemplates = @{} # Shared exception messages $script:bicepTemplateCompilationFailedException = "Unable to compile the main.bicep template's content. This can happen if there is an error in the template. Please check if you can run the command ``bicep build {0} --stdout | ConvertFrom-Json -AsHashtable``." # -f $templateFilePath -$script:jsonTemplateLoadFailedException = "Unable to load the main.json template's content. This can happen if there is an error in the template. Please check if you can run the command `Get-Content {0} -Raw | ConvertFrom-Json -AsHashtable`." # -f $templateFilePath $script:templateNotFoundException = 'No template file found in folder [{0}]' # -f $moduleFolderPath # Import any helper function used in this test script @@ -203,24 +202,14 @@ Describe 'Module tests' -Tag 'Module' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } - } - elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'main.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } - else { + } else { throw ($templateNotFoundException -f $moduleFolderPath) } $convertedTemplates[$moduleFolderPathKey] = @{ templateFilePath = $templateFilePath templateContent = $templateContent } - } - else { + } else { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath } @@ -342,24 +331,14 @@ Describe 'Module tests' -Tag 'Module' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } - } - elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'main.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } - else { + } else { throw ($templateNotFoundException -f $moduleFolderPath) } $convertedTemplates[$moduleFolderPathKey] = @{ templateFilePath = $templateFilePath templateContent = $templateContent } - } - else { + } else { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath } @@ -423,17 +402,13 @@ Describe 'Module tests' -Tag 'Module' { $SchemaArray = @() if ($Schemaverion -eq $RgDeploymentSchema) { $SchemaOutput = $true - } - elseIf ($Schemaverion -eq $SubscriptionDeploymentSchema) { + } elseIf ($Schemaverion -eq $SubscriptionDeploymentSchema) { $SchemaOutput = $true - } - elseIf ($Schemaverion -eq $MgDeploymentSchema) { + } elseIf ($Schemaverion -eq $MgDeploymentSchema) { $SchemaOutput = $true - } - elseIf ($Schemaverion -eq $TenantDeploymentSchema) { + } elseIf ($Schemaverion -eq $TenantDeploymentSchema) { $SchemaOutput = $true - } - else { + } else { $SchemaOutput = $false } $SchemaArray += $SchemaOutput @@ -496,8 +471,7 @@ Describe 'Module tests' -Tag 'Module' { foreach ($Param in $Parameter) { if ($Param.substring(0, 1) -cnotmatch '[a-z]' -or $Param -match '-' -or $Param -match '_') { $CamelCasingFlag += $false - } - else { + } else { $CamelCasingFlag += $true } } @@ -522,8 +496,7 @@ Describe 'Module tests' -Tag 'Module' { foreach ($Variab in $Variable) { if ($Variab.substring(0, 1) -cnotmatch '[a-z]' -or $Variab -match '-') { $CamelCasingFlag += $false - } - else { + } else { $CamelCasingFlag += $true } } @@ -542,8 +515,7 @@ Describe 'Module tests' -Tag 'Module' { foreach ($Output in $Outputs) { if ($Output.substring(0, 1) -cnotmatch '[a-z]' -or $Output -match '-' -or $Output -match '_') { $CamelCasingFlag += $false - } - else { + } else { $CamelCasingFlag += $true } } @@ -560,8 +532,7 @@ Describe 'Module tests' -Tag 'Module' { # With the introduction of user defined types, the way resources are configured in the schema slightly changed. We have to account for that. if ($templateContent.resources.GetType().Name -eq 'Object[]') { $templateResources = $templateContent.resources - } - else { + } else { $templateResources = $templateContent.resources.Keys | ForEach-Object { $templateContent.resources[$_] } } @@ -579,8 +550,7 @@ Describe 'Module tests' -Tag 'Module' { # With the introduction of user defined types, the way resources are configured in the schema slightly changed. We have to account for that. if ($templateContent.resources.GetType().Name -eq 'Object[]') { $templateResources = $templateContent.resources - } - else { + } else { $templateResources = $templateContent.resources.Keys | ForEach-Object { $templateContent.resources[$_] } } @@ -604,8 +574,7 @@ Describe 'Module tests' -Tag 'Module' { # With the introduction of user defined types, the way resources are configured in the schema slightly changed. We have to account for that. if ($templateContent.resources.GetType().Name -eq 'Object[]') { $templateResources = $templateContent.resources - } - else { + } else { $templateResources = $templateContent.resources.Keys | ForEach-Object { $templateContent.resources[$_] } } @@ -634,8 +603,7 @@ Describe 'Module tests' -Tag 'Module' { if ($Locationparamoutput -contains 'Location') { if ($Locationparamoutputvalue -eq '[resourceGroup().Location]' -or $Locationparamoutputvalue -eq 'global') { $LocationFlag = $true - } - else { + } else { $LocationFlag = $false } @@ -696,8 +664,7 @@ Describe 'Module tests' -Tag 'Module' { $readMeFileContentHeader = (Get-Content -Path $readMeFilePath)[0] if ($readMeFileContentHeader -match '^.*`\[(.+)\]`.*') { $primaryResourceType = $matches[1] - } - else { + } else { Write-Error "Cannot identity primary resource type in readme header [$readMeFileContentHeader] and cannot execute the test." return } @@ -705,8 +672,7 @@ Describe 'Module tests' -Tag 'Module' { # With the introduction of user defined types, the way resources are configured in the schema slightly changed. We have to account for that. if ($templateContent.resources.GetType().Name -eq 'Object[]') { $templateResources = $templateContent.resources - } - else { + } else { $templateResources = $templateContent.resources.Keys | ForEach-Object { $templateContent.resources[$_] } } @@ -732,8 +698,7 @@ Describe 'Module tests' -Tag 'Module' { $readMeFileContentHeader = (Get-Content -Path $readMeFilePath)[0] if ($readMeFileContentHeader -match '^.*`\[(.+)\]`.*') { $primaryResourceType = $matches[1] - } - else { + } else { Write-Error "Cannot identity primary resource type in readme header [$readMeFileContentHeader] and cannot execute the test." return } @@ -741,8 +706,7 @@ Describe 'Module tests' -Tag 'Module' { # With the introduction of user defined types, the way resources are configured in the schema slightly changed. We have to account for that. if ($templateContent.resources.GetType().Name -eq 'Object[]') { $templateResources = $templateContent.resources - } - else { + } else { $templateResources = $templateContent.resources.Keys | ForEach-Object { $templateContent.resources[$_] } } @@ -856,7 +820,6 @@ Describe 'Module tests' -Tag 'Module' { $incorrectOutputs | Should -BeNullOrEmpty } - # Update to work with nullable parameters It '[] All non-required parameters in template file should not have description that start with "Required.".' -TestCases $deploymentFolderTestCases { param ( [hashtable[]] $testFileTestCases, @@ -895,23 +858,13 @@ Describe 'Module tests' -Tag 'Module' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } - } - elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'main.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } - else { + } else { throw ($templateNotFoundException -f $moduleFolderPath) } $convertedTemplates[$moduleFolderPathKey] = @{ templateContent = $templateContent } - } - else { + } else { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent } @@ -954,6 +907,96 @@ Describe 'Module tests' -Tag 'Module' { $templateFileContent.metadata.owner | Should -Not -BeNullOrEmpty } } + + Context 'User-defined-types tests' -Tag 'UDT' { + + $udtTestCases = [System.Collections.ArrayList] @() + foreach ($moduleFolderPath in $moduleFolderPaths) { + + $resourceTypeIdentifier = ($moduleFolderPath -split '[\/|\\]{1}avm[\/|\\]{1}(res|ptn)[\/|\\]{1}')[2] -replace '\\', '/' # avm/res// + + # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key + $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/avm/')[1].Trim('/').Replace('/', '-') + if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { + if (Test-Path (Join-Path $moduleFolderPath 'main.bicep')) { + $templateFilePath = Join-Path $moduleFolderPath 'main.bicep' + $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable + + if (-not $templateContent) { + throw ($bicepTemplateCompilationFailedException -f $templateFilePath) + } + } else { + throw ($templateNotFoundException -f $moduleFolderPath) + } + $convertedTemplates[$moduleFolderPathKey] = @{ + templateContent = $templateContent + } + } else { + $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + } + + $udtTestCases += @{ + moduleFolderName = $resourceTypeIdentifier + templateFileContent = $templateContent + } + } + + + It "[] If template has [roleAssignments] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + + param( + [object[]] $templateFileContent + ) + throw 'Not implemented' + + } + + It "[] If template has [privateEndpoints] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + + param( + [object[]] $templateFileContent + ) + throw 'Not implemented' + + } + + It "[] If template has [diagnosticSettings] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + + param( + [object[]] $templateFileContent + ) + throw 'Not implemented' + + } + + It "[] If template has [lock] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + + param( + [object[]] $templateFileContent + ) + throw 'Not implemented' + + } + + It "[] If template has [customerManagedKey] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + + param( + [object[]] $templateFileContent + ) + throw 'Not implemented' + + } + + It "[] If template has [diagnosticSettings] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + + param( + [object[]] $templateFileContent + ) + throw 'Not implemented' + + } + + } } Describe 'Test file tests' -Tag 'TestTemplate' { @@ -978,6 +1021,74 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } + It "[] Bicep test deployment files should contain serviceShort parameter" -TestCases $deploymentTestFileTestCases { + + param( + [object[]] $testFileContent + ) + throw 'Not implemented' + + } + + It "[] Bicep test deployment files in a [default] folder should contain a service short with ending [min]" -TestCases $deploymentTestFileTestCases { + + param( + [string] $testFilePath, + [object[]] $testFileContent + ) + #TODO: must consider that the folder name is more than just 'default' + throw 'Not implemented' + + } + + It "[] Bicep test deployment files in a [max] folder should contain a service short with ending [max]" -TestCases $deploymentTestFileTestCases { + + param( + [string] $testFilePath, + [object[]] $testFileContent + ) + #TODO: must consider that the folder name is more than just 'max' + throw 'Not implemented' + + } + + It "[] Bicep test deployment files in a [waf-aligned] folder should contain a service short with ending [waf]" -TestCases $deploymentTestFileTestCases { + + param( + [string] $testFilePath, + [object[]] $testFileContent + ) + #TODO: must consider that the folder name is more than just 'waf' + throw 'Not implemented' + + } + + It "[] Bicep test deployment files should contain a test name" -TestCases $deploymentTestFileTestCases { + + param( + [object[]] $testFileContent + ) + throw 'Not implemented' + + } + + It "[] Bicep test deployment files should contain a test description" -TestCases $deploymentTestFileTestCases { + + param( + [object[]] $testFileContent + ) + throw 'Not implemented' + + } + + It "[] Bicep test deployment files should contain namePrefix parameter with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { + + param( + [object[]] $testFileContent + ) + throw 'Not implemented' + } + It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { param( @@ -1021,8 +1132,7 @@ Describe 'API version tests' -Tag 'ApiCheck' { try { $apiSpecs = Invoke-WebRequest -Uri $ApiSpecsFileUri $ApiVersions = ConvertFrom-Json $apiSpecs.Content -AsHashtable - } - catch { + } catch { Write-Warning "Failed to download API specs file from [$ApiSpecsFileUri]. Skipping API tests" Set-ItResult -Skipped -Because "Failed to download API specs file from [$ApiSpecsFileUri]. Skipping API tests." return @@ -1042,24 +1152,14 @@ Describe 'API version tests' -Tag 'ApiCheck' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } - } - elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { - $templateFilePath = Join-Path $moduleFolderPath 'main.json' - $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($jsonTemplateLoadFailedException -f $templateFilePath) - } - } - else { + } else { throw ($templateNotFoundException -f $moduleFolderPath) } $convertedTemplates[$moduleFolderPathKey] = @{ templateFilePath = $templateFilePath templateContent = $templateContent } - } - else { + } else { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath } @@ -1165,8 +1265,7 @@ Describe 'API version tests' -Tag 'ApiCheck' { # We allow the latest 5 including previews (in case somebody wants to use preview), or the latest 3 non-preview $approvedApiVersions += $resourceTypeApiVersions | Select-Object -Last 5 $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 5 - } - else { + } else { # We allow the latest 5 non-preview preview $approvedApiVersions += $resourceTypeApiVersions | Where-Object { $_ -notlike '*-preview' } | Select-Object -Last 5 } @@ -1179,8 +1278,7 @@ Describe 'API version tests' -Tag 'ApiCheck' { # The original failed test was # $approvedApiVersions | Should -Contain $TargetApi - } - else { + } else { # Provide a warning if an API version is second to next to expire. $indexOfVersion = $approvedApiVersions.IndexOf($TargetApi) From 4939b4d2e85ac2db8d8b2a67cb17fac7363196c7 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 00:38:44 +0100 Subject: [PATCH 02/35] Implemented first new tests --- avm/res/key-vault/vault/main.bicep | 3 - avm/res/key-vault/vault/main.json | 26 +-- .../compliance/module.tests.ps1 | 148 +++++++++++------- 3 files changed, 103 insertions(+), 74 deletions(-) diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index ae038cf1f5..4e62950d9c 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -353,9 +353,6 @@ type roleAssignmentType = { @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') condition: string? - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - @description('Optional. The Resource Id of the delegated managed identity resource.') delegatedManagedIdentityResourceId: string? }[]? diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index f10c40c0fb..bfcfb41b93 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "9188769706526490100" + "version": "0.23.1.45101", + "templateHash": "8353941507512521049" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -164,16 +164,6 @@ "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" } }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, "delegatedManagedIdentityResourceId": { "type": "string", "nullable": true, @@ -682,8 +672,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "9999250509448584761" + "version": "0.23.1.45101", + "templateHash": "4111939022872407830" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", @@ -815,8 +805,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "11139788551431901948" + "version": "0.23.1.45101", + "templateHash": "9180551172362989336" }, "name": "Key Vault Secrets", "description": "This module deploys a Key Vault Secret.", @@ -1104,8 +1094,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "15591839680984542683" + "version": "0.23.1.45101", + "templateHash": "2691621623448325959" }, "name": "Key Vault Keys", "description": "This module deploys a Key Vault Key.", diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index c1a0174819..f3ab52891e 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -935,67 +935,109 @@ Describe 'Module tests' -Tag 'Module' { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent } - $udtTestCases += @{ - moduleFolderName = $resourceTypeIdentifier - templateFileContent = $templateContent - } - } - - - It "[] If template has [roleAssignments] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { - - param( - [object[]] $templateFileContent + # Setting expected URL only for those that doen't have multiple different variants + $avmInterfaceSpecsBase = 'https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/main/docs/static/includes/interfaces' + $udtCases = @( + @{ + parameterName = 'diagnosticSettings' + udtName = 'diagnosticSettingType' + } + @{ + parameterName = 'roleAssignments' + udtName = 'roleAssignmentType' + udtExpectedUrl = "$avmInterfaceSpecsBase/int.rbac.udt.schema.bicep" + } + @{ + parameterName = 'lock' + udtName = 'lockType' + udtExpectedUrl = "$avmInterfaceSpecsBase/int.locks.udt.schema.bicep" + } + @{ + parameterName = 'managedIdentities' + udtName = 'managedIdentitiesType' + } + @{ + parameterName = 'privateEndpoints' + udtName = 'privateEndpointType' + } + @{ + parameterName = 'customerManagedKey' + udtName = 'customerManagedKeyType' + } ) - throw 'Not implemented' + foreach ($udtCase in $udtCases) { + $udtTestCases += @{ + moduleFolderName = $resourceTypeIdentifier + templateFileContent = $templateContent + templateFileContentBicep = Get-Content $templateFilePath + parameterName = $udtCase.parameterName + udtName = $udtCase.udtName + expectedUdtUrl = $udtCase.udtExpectedUrl ? $udtCase.udtExpectedUrl : '' + } + } } - It "[] If template has [privateEndpoints] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { - param( - [object[]] $templateFileContent - ) - throw 'Not implemented' - - } - - It "[] If template has [diagnosticSettings] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + It "[] If template has [] parameter, it should implement the expected user-defined type []" -TestCases $udtTestCases { param( - [object[]] $templateFileContent + [hashtable] $templateFileContent, + [string[]] $templateFileContentBicep, + [string] $parameterName, + [string] $udtName, + [string] $expectedUdtUrl ) - throw 'Not implemented' - - } - It "[] If template has [lock] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + if ($templateFileContent.parameters.Keys -contains $parameterName) { + $templateFileContent.parameters.$parameterName.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type." + $templateFileContent.parameters.$parameterName.'$ref' | Should -Be "#/definitions/$udtName" -Because "the [$parameterName] parameter should use a user-defined type [$udtName]." - param( - [object[]] $templateFileContent - ) - throw 'Not implemented' - - } - - It "[] If template has [customerManagedKey] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { + if (-not [String]::IsNullOrEmpty($expectedUdtUrl)) { + $implementedSchemaStartIndex = $templateFileContentBicep.IndexOf("type $udtName = {") + $implementedSchemaEndIndex = $implementedSchemaStartIndex + 1 + while ($templateFileContentBicep[$implementedSchemaEndIndex] -notmatch '^\}.*' -and $implementedSchemaEndIndex -lt $templateFileContentBicep.Length) { + $implementedSchemaEndIndex++ + } + if ($implementedSchemaEndIndex -eq $templateFileContentBicep.Length) { + throw "Failed to identify [$udtName] user-defined type in template." + } + $implementedSchema = $templateFileContentBicep[$implementedSchemaStartIndex..$implementedSchemaEndIndex] - param( - [object[]] $templateFileContent - ) - throw 'Not implemented' + $expectedSchemaFull = (Invoke-WebRequest -Uri $expectedUdtUrl).Content -split "\n" + $expectedSchemaStartIndex = $expectedSchemaFull.IndexOf("type $udtName = {") + $expectedSchemaEndIndex = $expectedSchemaStartIndex + 1 + while ($expectedSchemaFull[$expectedSchemaEndIndex] -notmatch '^\}.*' -and $expectedSchemaEndIndex -lt $expectedSchemaFull.Length) { + $expectedSchemaEndIndex++ + } + if ($expectedSchemaEndIndex -eq $expectedSchemaFull.Length) { + throw "Failed to identify [$udtName] user-defined type in expected schema at URL [$expectedUdtUrl]." + } + $expectedSchema = $expectedSchemaFull[$expectedSchemaStartIndex..$expectedSchemaEndIndex] + + $formattedDiff = @() + foreach ($finding in (Compare-Object $implementedSchema $expectedSchema)) { + if ($finding.SideIndicator -eq '=>') { + $formattedDiff += ('+ {0}' -f $finding.InputObject) + } elseif ($finding.SideIndicator -eq '<=') { + $formattedDiff += ('- {0}' -f $finding.InputObject) + } + } + if ($formattedDiff.Count -gt 0) { + Write-Warning ($formattedDiff | Out-String) -Verbose + $mdFormattedDiff = ($formattedDiff -join '
') -replace '\|', '\|' + } + ($implementedSchema | Out-String) | Should -Be ($expectedSchema | Out-String) -Because ('The implemented user-defined type should be the same as the expected user-defined type of url [{0}] and should not have diff
{1}
.' -f $expectedUdtUrl, $mdFormattedDiff) + } + } else { + Set-ItResult -Skipped -Because "the module template has no [$parameterName] parameter." + } } - It "[] If template has [diagnosticSettings] parameter, it should implement the expected user-defined-type" -TestCases $udtTestCases { - - param( - [object[]] $templateFileContent - ) - throw 'Not implemented' - - } + # TODO Add test for tags + # TODO add tests for msi principal id output } } @@ -1026,7 +1068,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - throw 'Not implemented' + Write-Error 'Not implemented' } @@ -1037,7 +1079,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { [object[]] $testFileContent ) #TODO: must consider that the folder name is more than just 'default' - throw 'Not implemented' + Write-Error 'Not implemented' } @@ -1048,7 +1090,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { [object[]] $testFileContent ) #TODO: must consider that the folder name is more than just 'max' - throw 'Not implemented' + Write-Error 'Not implemented' } @@ -1059,7 +1101,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { [object[]] $testFileContent ) #TODO: must consider that the folder name is more than just 'waf' - throw 'Not implemented' + Write-Error 'Not implemented' } @@ -1068,7 +1110,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - throw 'Not implemented' + Write-Error 'Not implemented' } @@ -1077,7 +1119,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - throw 'Not implemented' + Write-Error 'Not implemented' } @@ -1086,7 +1128,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - throw 'Not implemented' + Write-Error 'Not implemented' } It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { From 4e1d86f3848f9aa4e858f834bb373af04d64c179 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 09:19:19 +0100 Subject: [PATCH 03/35] Changed to warning --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index f3ab52891e..dd9c9fb5e1 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1023,12 +1023,10 @@ Describe 'Module tests' -Tag 'Module' { $formattedDiff += ('- {0}' -f $finding.InputObject) } } + if ($formattedDiff.Count -gt 0) { - Write-Warning ($formattedDiff | Out-String) -Verbose - $mdFormattedDiff = ($formattedDiff -join '
') -replace '\|', '\|' + Write-Warning ("The implemented user-defined type should be the same as the expected user-defined type of url [{0}] and should not have diff`n{1}" -f $expectedUdtUrl, ($formattedDiff | Out-String)) } - - ($implementedSchema | Out-String) | Should -Be ($expectedSchema | Out-String) -Because ('The implemented user-defined type should be the same as the expected user-defined type of url [{0}] and should not have diff
{1}
.' -f $expectedUdtUrl, $mdFormattedDiff) } } else { Set-ItResult -Skipped -Because "the module template has no [$parameterName] parameter." From 94fff0ba27001ed731cd18daee02d1b06b7cef21 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 14:19:32 +0100 Subject: [PATCH 04/35] Expanded test verbosity & added additional tets --- .../compliance/module.tests.ps1 | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index dd9c9fb5e1..cc36fb716e 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -910,7 +910,8 @@ Describe 'Module tests' -Tag 'Module' { Context 'User-defined-types tests' -Tag 'UDT' { - $udtTestCases = [System.Collections.ArrayList] @() + $udtTestCases = [System.Collections.ArrayList] @() # General UDT tests (e.g. param should exist) + $udtSpecificTestCases = [System.Collections.ArrayList] @() # Specific UDT test cases for singular UDTs (e.g. tags) foreach ($moduleFolderPath in $moduleFolderPaths) { $resourceTypeIdentifier = ($moduleFolderPath -split '[\/|\\]{1}avm[\/|\\]{1}(res|ptn)[\/|\\]{1}')[2] -replace '\\', '/' # avm/res// @@ -935,34 +936,47 @@ Describe 'Module tests' -Tag 'Module' { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent } + $udtSpecificTestCases += @{ + moduleFolderName = $resourceTypeIdentifier + templateFileContent = $templateContent + templateFileContentBicep = Get-Content $templateFilePath + } + # Setting expected URL only for those that doen't have multiple different variants - $avmInterfaceSpecsBase = 'https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/main/docs/static/includes/interfaces' + $avmInterfaceSpecsTemplateBase = 'https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/main/docs/static/includes/interfaces' + $avmInterfaceSpecsBase = 'https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces' $udtCases = @( @{ parameterName = 'diagnosticSettings' udtName = 'diagnosticSettingType' + link = "$avmInterfaceSpecsBase#diagnostic-settings" } @{ parameterName = 'roleAssignments' udtName = 'roleAssignmentType' - udtExpectedUrl = "$avmInterfaceSpecsBase/int.rbac.udt.schema.bicep" + udtExpectedUrl = "$avmInterfaceSpecsTemplateBase/int.rbac.udt.schema.bicep" + link = "$avmInterfaceSpecsBase#role-assignments" } @{ parameterName = 'lock' udtName = 'lockType' - udtExpectedUrl = "$avmInterfaceSpecsBase/int.locks.udt.schema.bicep" + udtExpectedUrl = "$avmInterfaceSpecsTemplateBase/int.locks.udt.schema.bicep" + link = "$avmInterfaceSpecsBase#resource-locks" } @{ parameterName = 'managedIdentities' udtName = 'managedIdentitiesType' + link = "$avmInterfaceSpecsBase#managed-identities" } @{ parameterName = 'privateEndpoints' udtName = 'privateEndpointType' + link = "$avmInterfaceSpecsBase#private-endpoints" } @{ parameterName = 'customerManagedKey' udtName = 'customerManagedKeyType' + link = "$avmInterfaceSpecsBase#customer-managed-keys" } ) @@ -979,19 +993,20 @@ Describe 'Module tests' -Tag 'Module' { } - It "[] If template has [] parameter, it should implement the expected user-defined type []" -TestCases $udtTestCases { + It "[] If template has [] parameter, it should implement the user-defined type []" -TestCases $udtTestCases { param( [hashtable] $templateFileContent, [string[]] $templateFileContentBicep, [string] $parameterName, [string] $udtName, - [string] $expectedUdtUrl + [string] $expectedUdtUrl, + [string] $link ) if ($templateFileContent.parameters.Keys -contains $parameterName) { - $templateFileContent.parameters.$parameterName.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type." - $templateFileContent.parameters.$parameterName.'$ref' | Should -Be "#/definitions/$udtName" -Because "the [$parameterName] parameter should use a user-defined type [$udtName]." + $templateFileContent.parameters.$parameterName.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type. For for information please review the [AVM Specs]($link)." + $templateFileContent.parameters.$parameterName.'$ref' | Should -Be "#/definitions/$udtName" -Because "the [$parameterName] parameter should use a user-defined type [$udtName]. For for information please review the [AVM Specs]($link)." if (-not [String]::IsNullOrEmpty($expectedUdtUrl)) { $implementedSchemaStartIndex = $templateFileContentBicep.IndexOf("type $udtName = {") @@ -1025,7 +1040,7 @@ Describe 'Module tests' -Tag 'Module' { } if ($formattedDiff.Count -gt 0) { - Write-Warning ("The implemented user-defined type should be the same as the expected user-defined type of url [{0}] and should not have diff`n{1}" -f $expectedUdtUrl, ($formattedDiff | Out-String)) + Write-Warning ("The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String)) } } } else { @@ -1033,9 +1048,31 @@ Describe 'Module tests' -Tag 'Module' { } } + It "[] If a [managedIdentitiesType] UDT definition exists and supports system-assigned-identities, the template should have an output for its principal ID." -TestCases $udtSpecificTestCases { + + param( + [hashtable] $templateFileContent + ) + + if ($templateFileContent.definitions.Keys -contains 'managedIdentitiesType' -and $templateFileContent.definitions.managedIdentitiesType.properties.keys -contains 'systemAssigned') { + $templateFileContent.outputs.Keys | Should -Contain 'systemAssignedMIPrincipalId' -Because 'The AVM specs require a this output. For for information please review the [AVM Specs](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces#managed-identities).' + } else { + Set-ItResult -Skipped -Because "the module template has no [managedIdentitiesType] UDT definition or does not support system-assigned-identities." + } + } + + It "[] If a [tags] parameter exists it should be nullable." -TestCases $udtTestCases { - # TODO Add test for tags - # TODO add tests for msi principal id output + param( + [hashtable] $templateFileContent + ) + + if ($templateFileContent.parameters.Keys -contains 'tags') { + $templateFileContent.parameters.tags.nullable | Should -Be $true -Because 'The AVM specs require a specific format. For for information please review the [AVM Specs](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces#tags).' + } else { + Set-ItResult -Skipped -Because "the module template has no [tags] parameter." + } + } } } From c18ce6baea39a873b231c956c2439b3913935dc1 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 15:45:41 +0100 Subject: [PATCH 05/35] Finalized further tests --- .../compliance/module.tests.ps1 | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index cc36fb716e..24dbbc5c5f 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1061,7 +1061,7 @@ Describe 'Module tests' -Tag 'Module' { } } - It "[] If a [tags] parameter exists it should be nullable." -TestCases $udtTestCases { + It "[] If a [tags] parameter exists it should be nullable." -TestCases $udtSpecificTestCases { param( [hashtable] $templateFileContent @@ -1103,41 +1103,49 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - Write-Error 'Not implemented' - + ($testFileContent -match "^param serviceShort string = '(.*)$") | Should -Not -BeNullOrEmpty -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*''].' } - It "[] Bicep test deployment files in a [default] folder should contain a service short with ending [min]" -TestCases $deploymentTestFileTestCases { + It "[] Bicep test deployment files in a [default] folder should contain a service short with ending [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { param( - [string] $testFilePath, [object[]] $testFileContent ) - #TODO: must consider that the folder name is more than just 'default' - Write-Error 'Not implemented' + if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { + $serviceShort = $Matches[1] + $serviceShort | Should -BeLike "*min" + } else { + Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*min''] but it doesn''t.' + } } - It "[] Bicep test deployment files in a [max] folder should contain a service short with ending [max]" -TestCases $deploymentTestFileTestCases { + It "[] Bicep test deployment files in a [max] folder should contain a service short with ending [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { param( - [string] $testFilePath, [object[]] $testFileContent ) - #TODO: must consider that the folder name is more than just 'max' - Write-Error 'Not implemented' + if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { + $serviceShort = $Matches[1] + $serviceShort | Should -BeLike "*max" + } else { + Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*max''] but it doesn''t.' + } } - It "[] Bicep test deployment files in a [waf-aligned] folder should contain a service short with ending [waf]" -TestCases $deploymentTestFileTestCases { + It "[] Bicep test deployment files in a [waf-aligned] folder should contain a service short with ending [waf]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]waf\-aligned[\\|\/].*' }) { param( - [string] $testFilePath, [object[]] $testFileContent ) - #TODO: must consider that the folder name is more than just 'waf' - Write-Error 'Not implemented' + if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { + $serviceShort = $Matches[1] + $serviceShort | Should -BeLike "*waf" + } else { + Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*waf''] but it doesn''t.' + } } It "[] Bicep test deployment files should contain a test name" -TestCases $deploymentTestFileTestCases { From a3436942147ce7690ab14a9c12ce11f1bc5c628b Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 16:18:05 +0100 Subject: [PATCH 06/35] Update to latest --- .../staticValidation/compliance/module.tests.ps1 | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 24dbbc5c5f..98caa78e5d 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1113,8 +1113,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { ) if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { - $serviceShort = $Matches[1] - $serviceShort | Should -BeLike "*min" + $Matches[1] | Should -BeLike "*min" } else { Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*min''] but it doesn''t.' } @@ -1127,8 +1126,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { ) if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { - $serviceShort = $Matches[1] - $serviceShort | Should -BeLike "*max" + $Matches[1] | Should -BeLike "*max" } else { Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*max''] but it doesn''t.' } @@ -1141,8 +1139,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { ) if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { - $serviceShort = $Matches[1] - $serviceShort | Should -BeLike "*waf" + $Matches[1] | Should -BeLike "*waf" } else { Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*waf''] but it doesn''t.' } @@ -1153,8 +1150,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - Write-Error 'Not implemented' - + (($testFileContent | Out-String) -match "metadata name = ") | Should -Be $true -Because 'Test cases should contain a test name in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } It "[] Bicep test deployment files should contain a test description" -TestCases $deploymentTestFileTestCases { @@ -1162,8 +1158,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - Write-Error 'Not implemented' - + (($testFileContent | Out-String) -match "metadata description = ") | Should -Be $true -Because 'Test cases should contain a test description in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } It "[] Bicep test deployment files should contain namePrefix parameter with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { From 3a6f0a2b56d426ce7e54bfc5145f45cf28dbd440 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 16:27:54 +0100 Subject: [PATCH 07/35] Update to latest --- .../staticValidation/compliance/module.tests.ps1 | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 98caa78e5d..013972eabb 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1150,7 +1150,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "metadata name = ") | Should -Be $true -Because 'Test cases should contain a test name in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' + (($testFileContent | Out-String) -match "metadata name = .+") | Should -Be $true -Because 'Test cases should contain a test name in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } It "[] Bicep test deployment files should contain a test description" -TestCases $deploymentTestFileTestCases { @@ -1158,7 +1158,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "metadata description = ") | Should -Be $true -Because 'Test cases should contain a test description in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' + (($testFileContent | Out-String) -match "metadata description = .+") | Should -Be $true -Because 'Test cases should contain a test description in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } It "[] Bicep test deployment files should contain namePrefix parameter with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { @@ -1166,7 +1166,9 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - Write-Error 'Not implemented' + + (($testFileContent | Out-String) -match "@description('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.')") | Should -Be $true -Because 'The parameter `namePrefix` should have a meaningful description.' + (($testFileContent | Out-String) -match "param namePrefix string = '#_namePrefix_#'") | Should -Be $true -Because 'The test CI needs this value to ensure that deployed resources have unique names.' } It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { From 4ab6a5bb23b592796960daf61cb831fcf91cd3ac Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 16:38:29 +0100 Subject: [PATCH 08/35] Added module name + small fix --- .../compliance/module.tests.ps1 | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 013972eabb..d5dd1215c6 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1090,6 +1090,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { $resourceTypeIdentifier = ($moduleFolderPath -split '[\/|\\]{1}avm[\/|\\]{1}(res|ptn)[\/|\\]{1}')[2] -replace '\\', '/' # avm/res// $deploymentTestFileTestCases += @{ + testName = Split-Path (Split-Path $testFilePath) -Leaf testFilePath = $testFilePath testFileContent = $testFileContent moduleFolderName = $resourceTypeIdentifier @@ -1098,7 +1099,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] Bicep test deployment files should contain serviceShort parameter" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain serviceShort parameter" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1106,7 +1107,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { ($testFileContent -match "^param serviceShort string = '(.*)$") | Should -Not -BeNullOrEmpty -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*''].' } - It "[] Bicep test deployment files in a [default] folder should contain a service short with ending [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [default] folder should contain a service short with ending [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { param( [object[]] $testFileContent @@ -1119,7 +1120,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] Bicep test deployment files in a [max] folder should contain a service short with ending [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [max] folder should contain a service short with ending [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { param( [object[]] $testFileContent @@ -1132,7 +1133,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] Bicep test deployment files in a [waf-aligned] folder should contain a service short with ending [waf]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]waf\-aligned[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [waf-aligned] folder should contain a service short with ending [waf]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]waf\-aligned[\\|\/].*' }) { param( [object[]] $testFileContent @@ -1145,7 +1146,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] Bicep test deployment files should contain a test name" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain a test name" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1153,7 +1154,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { (($testFileContent | Out-String) -match "metadata name = .+") | Should -Be $true -Because 'Test cases should contain a test name in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } - It "[] Bicep test deployment files should contain a test description" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain a test description" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1161,17 +1162,17 @@ Describe 'Test file tests' -Tag 'TestTemplate' { (($testFileContent | Out-String) -match "metadata description = .+") | Should -Be $true -Because 'Test cases should contain a test description in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } - It "[] Bicep test deployment files should contain namePrefix parameter with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain namePrefix parameter with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "@description('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.')") | Should -Be $true -Because 'The parameter `namePrefix` should have a meaningful description.' + (($testFileContent | Out-String) -match "@description\('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.'\)") | Should -Be $true -Because 'The parameter `namePrefix` should have a meaningful description.' (($testFileContent | Out-String) -match "param namePrefix string = '#_namePrefix_#'") | Should -Be $true -Because 'The test CI needs this value to ensure that deployed resources have unique names.' } - It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1182,7 +1183,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' } - It '[] Bicep test deployment name should contain [`-test-`].' -TestCases $deploymentTestFileTestCases { + It '[] [] Bicep test deployment name should contain [`-test-`].' -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1193,7 +1194,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' } - It '[] Bicep test deployment should have parameter [`serviceShort`].' -TestCases $deploymentTestFileTestCases { + It '[] [] Bicep test deployment should have parameter [`serviceShort`].' -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent From 9bb64bde34d8b5de3d1b2bda2a0fe2687855b35f Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 17:31:08 +0100 Subject: [PATCH 09/35] Fixed kvlt --- avm/res/key-vault/vault/access-policy/main.json | 4 ++-- avm/res/key-vault/vault/key/main.json | 4 ++-- avm/res/key-vault/vault/main.bicep | 3 +++ avm/res/key-vault/vault/main.json | 12 +++++++++++- avm/res/key-vault/vault/secret/main.json | 4 ++-- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/avm/res/key-vault/vault/access-policy/main.json b/avm/res/key-vault/vault/access-policy/main.json index 9b6725ecc4..8aa7ea483d 100644 --- a/avm/res/key-vault/vault/access-policy/main.json +++ b/avm/res/key-vault/vault/access-policy/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "9999250509448584761" + "version": "0.23.1.45101", + "templateHash": "4111939022872407830" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", diff --git a/avm/res/key-vault/vault/key/main.json b/avm/res/key-vault/vault/key/main.json index 6ecce215ac..6e85c7d6ad 100644 --- a/avm/res/key-vault/vault/key/main.json +++ b/avm/res/key-vault/vault/key/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "15591839680984542683" + "version": "0.23.1.45101", + "templateHash": "2691621623448325959" }, "name": "Key Vault Keys", "description": "This module deploys a Key Vault Key.", diff --git a/avm/res/key-vault/vault/main.bicep b/avm/res/key-vault/vault/main.bicep index 4e62950d9c..ae038cf1f5 100644 --- a/avm/res/key-vault/vault/main.bicep +++ b/avm/res/key-vault/vault/main.bicep @@ -353,6 +353,9 @@ type roleAssignmentType = { @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') condition: string? + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + @description('Optional. The Resource Id of the delegated managed identity resource.') delegatedManagedIdentityResourceId: string? }[]? diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index bfcfb41b93..8478ccde4e 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -6,7 +6,7 @@ "_generator": { "name": "bicep", "version": "0.23.1.45101", - "templateHash": "8353941507512521049" + "templateHash": "1913015049301539374" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -164,6 +164,16 @@ "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" } }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, "delegatedManagedIdentityResourceId": { "type": "string", "nullable": true, diff --git a/avm/res/key-vault/vault/secret/main.json b/avm/res/key-vault/vault/secret/main.json index 62c5c52a19..f778252db1 100644 --- a/avm/res/key-vault/vault/secret/main.json +++ b/avm/res/key-vault/vault/secret/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "11139788551431901948" + "version": "0.23.1.45101", + "templateHash": "9180551172362989336" }, "name": "Key Vault Secrets", "description": "This module deploys a Key Vault Secret.", From 68e2bd2fbc6301b199fd0258411da31781ba4380 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 17:56:38 +0100 Subject: [PATCH 10/35] Small caching fix --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index d5dd1215c6..8dc880fdb9 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -930,10 +930,12 @@ Describe 'Module tests' -Tag 'Module' { throw ($templateNotFoundException -f $moduleFolderPath) } $convertedTemplates[$moduleFolderPathKey] = @{ - templateContent = $templateContent + templateContent = $templateContent + templateFilePath = $templateFilePath } } else { $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent + $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath } $udtSpecificTestCases += @{ From 1a013c2a4115610d4260515205158ed831860de8 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 19:25:21 +0100 Subject: [PATCH 11/35] Small fix and enabled passthru of warnings to GH --- .../compliance/Set-PesterGitHubOutput.ps1 | 72 ++++++++++++++++--- .../compliance/module.tests.ps1 | 9 ++- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index 4c84e61eaf..ada2dc98e9 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -81,10 +81,12 @@ function Set-PesterGitHubOutput { $passedTests = $PesterTestResults.Passed $failedTests = $PesterTestResults.Failed $skippedTests = $PesterTestResults.Skipped + $testsWithWarnings = ($passedTests + $failedTests + $skippedTests) | Where-Object { $_.StandardOutput.Keys -eq 'Warning' } Write-Verbose ('Formatting [{0}] passed tests' -f $passedTests.Count) Write-Verbose ('Formatting [{0}] failed tests' -f $failedTests.Count) Write-Verbose ('Formatting [{0}] skipped tests' -f $skippedTests.Count) + Write-Verbose ('Formatting [{0}] tests with explicit warnings' -f $warnings.Count) ###################### # Set output content # @@ -98,9 +100,9 @@ function Set-PesterGitHubOutput { ## Header table $fileContent += [System.Collections.ArrayList]@( - '| Total No. of Processed Tests| Passed Tests :white_check_mark: | Failed Tests :x: | Skipped Tests :paperclip: |', - '| :-- | :-- | :-- | :-- |' - ('| {0} | {1} | {2} | {3} |' -f $PesterTestResults.TotalCount, $passedTests.count , $failedTests.count, $skippedTests.count), + '| Total No. of Processed Tests| Passed Tests :white_check_mark: | Failed Tests :x: | Skipped Tests :paperclip: | Tests with warnings :warning: |', + '| :-- | :-- | :-- | :-- |', + ('| {0} | {1} | {2} | {3} |' -f $PesterTestResults.TotalCount, $passedTests.count , $failedTests.count, $skippedTests.count, $testsWithWarnings.count), '' ) @@ -140,8 +142,7 @@ function Set-PesterGitHubOutput { $fileContent += '| {0} | {1} | {2} |' -f $testName, $errorMessage, $testReference } - } - else { + } else { $fileContent += ('No tests failed.') } @@ -164,6 +165,8 @@ function Set-PesterGitHubOutput { if (($passedTests.Count -gt 0)) { + # TODO: Add support for outputs + $fileContent += [System.Collections.ArrayList]@( '| Name | Source |', '| :-- | :-- |' @@ -185,8 +188,7 @@ function Set-PesterGitHubOutput { $fileContent += '| {0} | {1} |' -f $testName, $testReference } - } - else { + } else { $fileContent += ('No tests passed.') } @@ -222,8 +224,8 @@ function Set-PesterGitHubOutput { $reason = ('Test {0}' -f $skippedTest.ErrorRecord.Exception.Message -replace '\|', '\|').Trim() - $testLine = $passedTest.ScriptBlock.StartPosition.StartLine - $testFile = (($passedTest.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] + $testLine = $skippedTest.ScriptBlock.StartPosition.StartLine + $testFile = (($skippedTest.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] $testReference = '{0}:{1}' -f (Split-Path $testFile -Leaf), $testLine if (-not [String]::IsNullOrEmpty($GitHubRepository) -and -not [String]::IsNullOrEmpty($BranchName)) { @@ -233,8 +235,7 @@ function Set-PesterGitHubOutput { $fileContent += '| {0} | {1} | {2} |' -f $testName, $reason, $testReference } - } - else { + } else { $fileContent += ('No tests were skipped.') } @@ -244,6 +245,55 @@ function Set-PesterGitHubOutput { '' ) + ################## + ## Warnings ## + ################## + + Write-Verbose 'Adding warnings' + $fileContent += [System.Collections.ArrayList]@( + '', + '
', + 'List of explicit warnings', + '' + ) + + if ($testsWithWarnings.Count -gt 0) { + + $fileContent += [System.Collections.ArrayList]@( + '| Name | Warning | Source |', + '| :-- | :-- | :-- |' + ) + foreach ($test in ($testsWithWarnings | Sort-Object -Property { $PSItem.ExpandedName }) ) { + foreach ($warning in $test.StandardOutput.Warning) { + $intermediateNameElements = $test.Path + $intermediateNameElements[-1] = '**{0}**' -f $test.ExpandedName + $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() + + $testLine = $test.ScriptBlock.StartPosition.StartLine + $testFile = (($test.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] + + $testReference = '{0}:{1}' -f (Split-Path $testFile -Leaf), $testLine + if (-not [String]::IsNullOrEmpty($GitHubRepository) -and -not [String]::IsNullOrEmpty($BranchName)) { + # Creating URL to test file to enable users to 'click' on it + $testReference = "[$testReference](https://github.com/$GitHubRepository/blob/$BranchName/$testFile#L$testLine)" + } + + $fileContent += '| {0} | {1} | {2} |' -f $testName, ($warning -replace '\|', '\|'), $testReference + } + } + } else { + $fileContent += ('No tests with warnings.') + } + + $fileContent += [System.Collections.ArrayList]@( + '', + '
', + '' + ) + + + + if ($PSCmdlet.ShouldProcess("Test results file in path [$OutputFilePath]", 'Create')) { $null = New-Item -Path $OutputFilePath -Force -Value ($fileContent | Out-String) } diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 8dc880fdb9..8ba6483758 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -990,6 +990,7 @@ Describe 'Module tests' -Tag 'Module' { parameterName = $udtCase.parameterName udtName = $udtCase.udtName expectedUdtUrl = $udtCase.udtExpectedUrl ? $udtCase.udtExpectedUrl : '' + link = $udtCase.link } } } @@ -1042,7 +1043,13 @@ Describe 'Module tests' -Tag 'Module' { } if ($formattedDiff.Count -gt 0) { - Write-Warning ("The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String)) + $warningMessage = "The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String) + Write-Warning $warningMessage + + # Adding also to output to show in GitHub CI + Write-Output @{ + Warning = $warningMessage + } } } } else { From 1c2fc8ab54eafaef98ab28b8feaa3073d9469436 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 19:31:09 +0100 Subject: [PATCH 12/35] More updates --- .../staticValidation/compliance/Set-PesterGitHubOutput.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index ada2dc98e9..e716f14f5b 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -101,8 +101,8 @@ function Set-PesterGitHubOutput { ## Header table $fileContent += [System.Collections.ArrayList]@( '| Total No. of Processed Tests| Passed Tests :white_check_mark: | Failed Tests :x: | Skipped Tests :paperclip: | Tests with warnings :warning: |', - '| :-- | :-- | :-- | :-- |', - ('| {0} | {1} | {2} | {3} |' -f $PesterTestResults.TotalCount, $passedTests.count , $failedTests.count, $skippedTests.count, $testsWithWarnings.count), + '| :-- | :-- | :-- | :-- | :-- |', + ('| {0} | {1} | {2} | {3} | {4} |' -f $PesterTestResults.TotalCount, $passedTests.count , $failedTests.count, $skippedTests.count, $testsWithWarnings.count), '' ) @@ -278,7 +278,7 @@ function Set-PesterGitHubOutput { $testReference = "[$testReference](https://github.com/$GitHubRepository/blob/$BranchName/$testFile#L$testLine)" } - $fileContent += '| {0} | {1} | {2} |' -f $testName, ($warning -replace '\|', '\|'), $testReference + $fileContent += '| {0} | {1} | {2} |' -f $testName, (($warning -join '
') -replace '\|', '\|'), $testReference } } } else { From d9c6dd5deffd8fd307107e5ce8be98961163996a Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 20:16:57 +0100 Subject: [PATCH 13/35] Update to latest --- .../staticValidation/compliance/Set-PesterGitHubOutput.ps1 | 4 +--- .../pipelines/staticValidation/compliance/module.tests.ps1 | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index e716f14f5b..e1c207936d 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -165,8 +165,6 @@ function Set-PesterGitHubOutput { if (($passedTests.Count -gt 0)) { - # TODO: Add support for outputs - $fileContent += [System.Collections.ArrayList]@( '| Name | Source |', '| :-- | :-- |' @@ -278,7 +276,7 @@ function Set-PesterGitHubOutput { $testReference = "[$testReference](https://github.com/$GitHubRepository/blob/$BranchName/$testFile#L$testLine)" } - $fileContent += '| {0} | {1} | {2} |' -f $testName, (($warning -join '
') -replace '\|', '\|'), $testReference + $fileContent += ('| {0} | {1} | {2} |' -f $testName, $warning, $testReference) } } } else { diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 8ba6483758..997ac427a6 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1043,12 +1043,14 @@ Describe 'Module tests' -Tag 'Module' { } if ($formattedDiff.Count -gt 0) { - $warningMessage = "The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String) + $warningMessage = "The implemented user-defined type is not the same as the expected user-defined type ({0}) defined in the AVM specs ({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String) Write-Warning $warningMessage # Adding also to output to show in GitHub CI + $mdFormattedDiff = ($formattedDiff -join '
') -replace '\|', '\|' + $mdFormattedWarningMessage = "The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff
{2}
" -f $expectedUdtUrl, $link, $mdFormattedDiff Write-Output @{ - Warning = $warningMessage + Warning = $mdFormattedWarningMessage } } } From dd0c343fb884869740436c238b367d13029fc549 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 21:00:06 +0100 Subject: [PATCH 14/35] Updated test names --- .../compliance/module.tests.ps1 | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 997ac427a6..e46c6fc17d 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -996,7 +996,7 @@ Describe 'Module tests' -Tag 'Module' { } - It "[] If template has [] parameter, it should implement the user-defined type []" -TestCases $udtTestCases { + It "[] If template has a parameter [], it should implement the user-defined type []" -TestCases $udtTestCases { param( [hashtable] $templateFileContent, @@ -1059,7 +1059,7 @@ Describe 'Module tests' -Tag 'Module' { } } - It "[] If a [managedIdentitiesType] UDT definition exists and supports system-assigned-identities, the template should have an output for its principal ID." -TestCases $udtSpecificTestCases { + It "[] If a UDT definition [managedIdentitiesType] exists and supports system-assigned-identities, the template should have an output for its principal ID." -TestCases $udtSpecificTestCases { param( [hashtable] $templateFileContent @@ -1072,7 +1072,7 @@ Describe 'Module tests' -Tag 'Module' { } } - It "[] If a [tags] parameter exists it should be nullable." -TestCases $udtSpecificTestCases { + It "[] If a parameter [tags] exists it should be nullable." -TestCases $udtSpecificTestCases { param( [hashtable] $templateFileContent @@ -1110,15 +1110,15 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] [] Bicep test deployment files should contain serviceShort parameter" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain a parameter [serviceShort]" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent ) - ($testFileContent -match "^param serviceShort string = '(.*)$") | Should -Not -BeNullOrEmpty -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*''].' + ($testFileContent -match "^param serviceShort string = '(.*)$") | Should -Not -BeNullOrEmpty -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*''].' } - It "[] [] Bicep test deployment files in a [default] folder should contain a service short with ending [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [waf-aligned] folder should have a parameter [serviceShort] with a value ending with [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { param( [object[]] $testFileContent @@ -1127,11 +1127,11 @@ Describe 'Test file tests' -Tag 'TestTemplate' { if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { $Matches[1] | Should -BeLike "*min" } else { - Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*min''] but it doesn''t.' + Set-ItResult -Skipped -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*min''] but it doesn''t.' } } - It "[] [] Bicep test deployment files in a [max] folder should contain a service short with ending [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [waf-aligned] folder should have a [serviceShort] parameter with a value ending with [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { param( [object[]] $testFileContent @@ -1140,11 +1140,11 @@ Describe 'Test file tests' -Tag 'TestTemplate' { if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { $Matches[1] | Should -BeLike "*max" } else { - Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*max''] but it doesn''t.' + Set-ItResult -Skipped -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*max''] but it doesn''t.' } } - It "[] [] Bicep test deployment files in a [waf-aligned] folder should contain a service short with ending [waf]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]waf\-aligned[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [waf-aligned] folder should have a [serviceShort] parameter with a value ending with [waf]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]waf\-aligned[\\|\/].*' }) { param( [object[]] $testFileContent @@ -1153,34 +1153,34 @@ Describe 'Test file tests' -Tag 'TestTemplate' { if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { $Matches[1] | Should -BeLike "*waf" } else { - Set-ItResult -Skipped -Because 'the module test deployment file should contain a service short parameter using the syntax [param serviceShort string = ''*waf''] but it doesn''t.' + Set-ItResult -Skipped -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*waf''] but it doesn''t.' } } - It "[] [] Bicep test deployment files should contain a test name" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain a metadata string [name]" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "metadata name = .+") | Should -Be $true -Because 'Test cases should contain a test name in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' + (($testFileContent | Out-String) -match "metadata name = .+") | Should -Be $true -Because 'Test cases should contain a metadata string [name] in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } - It "[] [] Bicep test deployment files should contain a test description" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain a metadata string [description]" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "metadata description = .+") | Should -Be $true -Because 'Test cases should contain a test description in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' + (($testFileContent | Out-String) -match "metadata description = .+") | Should -Be $true -Because 'Test cases should contain a metadata string [description] in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } - It "[] [] Bicep test deployment files should contain namePrefix parameter with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { + It "[] [] Bicep test deployment files should contain a parameter [namePrefix] with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "@description\('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.'\)") | Should -Be $true -Because 'The parameter `namePrefix` should have a meaningful description.' - (($testFileContent | Out-String) -match "param namePrefix string = '#_namePrefix_#'") | Should -Be $true -Because 'The test CI needs this value to ensure that deployed resources have unique names.' + (($testFileContent | Out-String) -match "@description\('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.'\)") | Should -Be $true -Because 'The parameter [namePrefix] should have the expected description.' + (($testFileContent | Out-String) -match "param namePrefix string = '#_namePrefix_#'") | Should -Be $true -Because 'The test CI needs this value to ensure that deployed resources have unique names per fork.' } It "[] [] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { From 2ebd45891d75ce145710733437cb82c5814128c4 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 23:32:08 +0100 Subject: [PATCH 15/35] JSON rollback --- avm/res/key-vault/vault/access-policy/main.json | 4 ++-- avm/res/key-vault/vault/key/main.json | 4 ++-- avm/res/key-vault/vault/main.json | 16 ++++++++-------- avm/res/key-vault/vault/secret/main.json | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/avm/res/key-vault/vault/access-policy/main.json b/avm/res/key-vault/vault/access-policy/main.json index 8aa7ea483d..9b6725ecc4 100644 --- a/avm/res/key-vault/vault/access-policy/main.json +++ b/avm/res/key-vault/vault/access-policy/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4111939022872407830" + "version": "0.22.6.54827", + "templateHash": "9999250509448584761" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", diff --git a/avm/res/key-vault/vault/key/main.json b/avm/res/key-vault/vault/key/main.json index 6e85c7d6ad..6ecce215ac 100644 --- a/avm/res/key-vault/vault/key/main.json +++ b/avm/res/key-vault/vault/key/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2691621623448325959" + "version": "0.22.6.54827", + "templateHash": "15591839680984542683" }, "name": "Key Vault Keys", "description": "This module deploys a Key Vault Key.", diff --git a/avm/res/key-vault/vault/main.json b/avm/res/key-vault/vault/main.json index 8478ccde4e..f10c40c0fb 100644 --- a/avm/res/key-vault/vault/main.json +++ b/avm/res/key-vault/vault/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "1913015049301539374" + "version": "0.22.6.54827", + "templateHash": "9188769706526490100" }, "name": "Key Vaults", "description": "This module deploys a Key Vault.", @@ -682,8 +682,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "4111939022872407830" + "version": "0.22.6.54827", + "templateHash": "9999250509448584761" }, "name": "Key Vault Access Policies", "description": "This module deploys a Key Vault Access Policy.", @@ -815,8 +815,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "9180551172362989336" + "version": "0.22.6.54827", + "templateHash": "11139788551431901948" }, "name": "Key Vault Secrets", "description": "This module deploys a Key Vault Secret.", @@ -1104,8 +1104,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "2691621623448325959" + "version": "0.22.6.54827", + "templateHash": "15591839680984542683" }, "name": "Key Vault Keys", "description": "This module deploys a Key Vault Key.", diff --git a/avm/res/key-vault/vault/secret/main.json b/avm/res/key-vault/vault/secret/main.json index f778252db1..62c5c52a19 100644 --- a/avm/res/key-vault/vault/secret/main.json +++ b/avm/res/key-vault/vault/secret/main.json @@ -5,8 +5,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "9180551172362989336" + "version": "0.22.6.54827", + "templateHash": "11139788551431901948" }, "name": "Key Vault Secrets", "description": "This module deploys a Key Vault Secret.", From f6caf7e44eadf5ed72103aa3bcada9c3cf1c8fce Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 23:49:57 +0100 Subject: [PATCH 16/35] Updated regex --- .../compliance/Set-PesterGitHubOutput.ps1 | 2 +- .../staticValidation/compliance/module.tests.ps1 | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index e1c207936d..a8a773640e 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -131,7 +131,7 @@ function Set-PesterGitHubOutput { $errorTestLine = $failedTest.ErrorRecord.TargetObject.Line $errorTestFile = (($failedTest.ErrorRecord.TargetObject.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] - $errorMessage = $failedTest.ErrorRecord.TargetObject.Message.Trim() -replace '\n', '
' # Replace new lines with
to enable line breaks in markdown + $errorMessage = ($failedTest.ErrorRecord.TargetObject.Message.Trim() -replace '_', '\_') -replace '\n', '
' # Replace new lines with
to enable line breaks in markdown $testReference = '{0}:{1}' -f (Split-Path $errorTestFile -Leaf), $errorTestLine diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index e46c6fc17d..6b7c50807b 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1162,7 +1162,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "metadata name = .+") | Should -Be $true -Because 'Test cases should contain a metadata string [name] in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' + ($testFileContent | Out-String) | Should -Match "metadata name = .+" -Because 'Test cases should contain a metadata string [name] in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } It "[] [] Bicep test deployment files should contain a metadata string [description]" -TestCases $deploymentTestFileTestCases { @@ -1170,7 +1170,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { param( [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "metadata description = .+") | Should -Be $true -Because 'Test cases should contain a metadata string [description] in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' + ($testFileContent | Out-String) | Should -Match "metadata description = .+" -Because 'Test cases should contain a metadata string [description] in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' } It "[] [] Bicep test deployment files should contain a parameter [namePrefix] with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { @@ -1179,8 +1179,8 @@ Describe 'Test file tests' -Tag 'TestTemplate' { [object[]] $testFileContent ) - (($testFileContent | Out-String) -match "@description\('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.'\)") | Should -Be $true -Because 'The parameter [namePrefix] should have the expected description.' - (($testFileContent | Out-String) -match "param namePrefix string = '#_namePrefix_#'") | Should -Be $true -Because 'The test CI needs this value to ensure that deployed resources have unique names per fork.' + ($testFileContent | Out-String) | Should -Match "@description\('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.'\)" -Because 'The parameter [namePrefix] should have the expected description.' + ($testFileContent | Out-String) | Should -Match "param namePrefix string = '#_namePrefix_#'" -Because 'The test CI needs this value to ensure that deployed resources have unique names per fork.' } It "[] [] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { From f56f66af2a884495d5eeafb4f580d76960ee93f3 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 23:52:45 +0100 Subject: [PATCH 17/35] Removed assertion --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index 6b7c50807b..b7c9ab905f 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1179,7 +1179,6 @@ Describe 'Test file tests' -Tag 'TestTemplate' { [object[]] $testFileContent ) - ($testFileContent | Out-String) | Should -Match "@description\('Optional\. A token to inject into the name of each resource\. This value can be automatically injected by the CI\.'\)" -Because 'The parameter [namePrefix] should have the expected description.' ($testFileContent | Out-String) | Should -Match "param namePrefix string = '#_namePrefix_#'" -Because 'The test CI needs this value to ensure that deployed resources have unique names per fork.' } From 282b640a884885ba59db841457ddfdc5ea1ec59e Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 8 Nov 2023 23:58:17 +0100 Subject: [PATCH 18/35] Update to latest --- .../compliance/Set-PesterGitHubOutput.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index a8a773640e..d23f8d4f8f 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -127,7 +127,7 @@ function Set-PesterGitHubOutput { $intermediateNameElements = $failedTest.Path $intermediateNameElements[-1] = '**{0}**' -f $failedTest.ExpandedName - $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() + $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() $errorTestLine = $failedTest.ErrorRecord.TargetObject.Line $errorTestFile = (($failedTest.ErrorRecord.TargetObject.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] @@ -173,7 +173,7 @@ function Set-PesterGitHubOutput { $intermediateNameElements = $passedTest.Path $intermediateNameElements[-1] = '**{0}**' -f $passedTest.ExpandedName - $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() + $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() $testLine = $passedTest.ScriptBlock.StartPosition.StartLine $testFile = (($passedTest.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] @@ -218,7 +218,7 @@ function Set-PesterGitHubOutput { $intermediateNameElements = $skippedTest.Path $intermediateNameElements[-1] = '**{0}**' -f $skippedTest.ExpandedName - $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() + $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() $reason = ('Test {0}' -f $skippedTest.ErrorRecord.Exception.Message -replace '\|', '\|').Trim() @@ -265,7 +265,7 @@ function Set-PesterGitHubOutput { foreach ($warning in $test.StandardOutput.Warning) { $intermediateNameElements = $test.Path $intermediateNameElements[-1] = '**{0}**' -f $test.ExpandedName - $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() + $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() $testLine = $test.ScriptBlock.StartPosition.StartLine $testFile = (($test.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] From c025f526216b35a93c6ffee5dfe4beb3dc29cada Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Thu, 9 Nov 2023 07:32:30 +0100 Subject: [PATCH 19/35] Update avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index b7c9ab905f..cdd40eb5ed 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1131,7 +1131,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] [] Bicep test deployment files in a [waf-aligned] folder should have a [serviceShort] parameter with a value ending with [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [max] folder should have a [serviceShort] parameter with a value ending with [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { param( [object[]] $testFileContent From 405901aff9656cb669db03eb90cfb96f2fa13908 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Thu, 9 Nov 2023 07:33:08 +0100 Subject: [PATCH 20/35] Update avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 Co-authored-by: Erika Gressi <56914614+eriqua@users.noreply.github.com> --- .../pipelines/staticValidation/compliance/module.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index cdd40eb5ed..a2ac22d565 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -1118,7 +1118,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { ($testFileContent -match "^param serviceShort string = '(.*)$") | Should -Not -BeNullOrEmpty -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*''].' } - It "[] [] Bicep test deployment files in a [waf-aligned] folder should have a parameter [serviceShort] with a value ending with [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { + It "[] [] Bicep test deployment files in a [defaults] folder should have a parameter [serviceShort] with a value ending with [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { param( [object[]] $testFileContent From ef24d1f1e65cad599a9f8eaf311a4aa41f1452db Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Thu, 9 Nov 2023 19:29:56 +0100 Subject: [PATCH 21/35] Rollback of unrelated changes --- .../compliance/Set-PesterGitHubOutput.ps1 | 71 +---- .../compliance/module.tests.ps1 | 291 +++--------------- 2 files changed, 45 insertions(+), 317 deletions(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index d23f8d4f8f..66561b92fe 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -81,12 +81,10 @@ function Set-PesterGitHubOutput { $passedTests = $PesterTestResults.Passed $failedTests = $PesterTestResults.Failed $skippedTests = $PesterTestResults.Skipped - $testsWithWarnings = ($passedTests + $failedTests + $skippedTests) | Where-Object { $_.StandardOutput.Keys -eq 'Warning' } Write-Verbose ('Formatting [{0}] passed tests' -f $passedTests.Count) Write-Verbose ('Formatting [{0}] failed tests' -f $failedTests.Count) Write-Verbose ('Formatting [{0}] skipped tests' -f $skippedTests.Count) - Write-Verbose ('Formatting [{0}] tests with explicit warnings' -f $warnings.Count) ###################### # Set output content # @@ -100,9 +98,9 @@ function Set-PesterGitHubOutput { ## Header table $fileContent += [System.Collections.ArrayList]@( - '| Total No. of Processed Tests| Passed Tests :white_check_mark: | Failed Tests :x: | Skipped Tests :paperclip: | Tests with warnings :warning: |', - '| :-- | :-- | :-- | :-- | :-- |', - ('| {0} | {1} | {2} | {3} | {4} |' -f $PesterTestResults.TotalCount, $passedTests.count , $failedTests.count, $skippedTests.count, $testsWithWarnings.count), + '| Total No. of Processed Tests| Passed Tests :white_check_mark: | Failed Tests :x: | Skipped Tests :paperclip: |', + '| :-- | :-- | :-- | :-- |' + ('| {0} | {1} | {2} | {3} |' -f $PesterTestResults.TotalCount, $passedTests.count , $failedTests.count, $skippedTests.count), '' ) @@ -127,11 +125,11 @@ function Set-PesterGitHubOutput { $intermediateNameElements = $failedTest.Path $intermediateNameElements[-1] = '**{0}**' -f $failedTest.ExpandedName - $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() + $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() $errorTestLine = $failedTest.ErrorRecord.TargetObject.Line $errorTestFile = (($failedTest.ErrorRecord.TargetObject.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] - $errorMessage = ($failedTest.ErrorRecord.TargetObject.Message.Trim() -replace '_', '\_') -replace '\n', '
' # Replace new lines with
to enable line breaks in markdown + $errorMessage = $failedTest.ErrorRecord.TargetObject.Message.Trim() -replace '\n', '
' # Replace new lines with
to enable line breaks in markdown $testReference = '{0}:{1}' -f (Split-Path $errorTestFile -Leaf), $errorTestLine @@ -173,7 +171,7 @@ function Set-PesterGitHubOutput { $intermediateNameElements = $passedTest.Path $intermediateNameElements[-1] = '**{0}**' -f $passedTest.ExpandedName - $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() + $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() $testLine = $passedTest.ScriptBlock.StartPosition.StartLine $testFile = (($passedTest.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] @@ -218,12 +216,12 @@ function Set-PesterGitHubOutput { $intermediateNameElements = $skippedTest.Path $intermediateNameElements[-1] = '**{0}**' -f $skippedTest.ExpandedName - $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() + $testName = (($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|').Trim() $reason = ('Test {0}' -f $skippedTest.ErrorRecord.Exception.Message -replace '\|', '\|').Trim() - $testLine = $skippedTest.ScriptBlock.StartPosition.StartLine - $testFile = (($skippedTest.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] + $testLine = $passedTest.ScriptBlock.StartPosition.StartLine + $testFile = (($passedTest.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] $testReference = '{0}:{1}' -f (Split-Path $testFile -Leaf), $testLine if (-not [String]::IsNullOrEmpty($GitHubRepository) -and -not [String]::IsNullOrEmpty($BranchName)) { @@ -243,57 +241,8 @@ function Set-PesterGitHubOutput { '' ) - ################## - ## Warnings ## - ################## - - Write-Verbose 'Adding warnings' - $fileContent += [System.Collections.ArrayList]@( - '', - '
', - 'List of explicit warnings', - '' - ) - - if ($testsWithWarnings.Count -gt 0) { - - $fileContent += [System.Collections.ArrayList]@( - '| Name | Warning | Source |', - '| :-- | :-- | :-- |' - ) - foreach ($test in ($testsWithWarnings | Sort-Object -Property { $PSItem.ExpandedName }) ) { - foreach ($warning in $test.StandardOutput.Warning) { - $intermediateNameElements = $test.Path - $intermediateNameElements[-1] = '**{0}**' -f $test.ExpandedName - $testName = ((($intermediateNameElements -join ' / ' | Out-String) -replace '\|', '\|') -replace '_', '\_').Trim() - - $testLine = $test.ScriptBlock.StartPosition.StartLine - $testFile = (($test.ScriptBlock.File -split '[\/|\\](avm[\/|\\])')[-2, -1] -join '') -replace '\\', '/' # e.g., [avm\res\cognitive-services\account\tests\unit\custom.tests.ps1] - - $testReference = '{0}:{1}' -f (Split-Path $testFile -Leaf), $testLine - if (-not [String]::IsNullOrEmpty($GitHubRepository) -and -not [String]::IsNullOrEmpty($BranchName)) { - # Creating URL to test file to enable users to 'click' on it - $testReference = "[$testReference](https://github.com/$GitHubRepository/blob/$BranchName/$testFile#L$testLine)" - } - - $fileContent += ('| {0} | {1} | {2} |' -f $testName, $warning, $testReference) - } - } - } else { - $fileContent += ('No tests with warnings.') - } - - $fileContent += [System.Collections.ArrayList]@( - '', - '
', - '' - ) - - - - if ($PSCmdlet.ShouldProcess("Test results file in path [$OutputFilePath]", 'Create')) { $null = New-Item -Path $OutputFilePath -Force -Value ($fileContent | Out-String) } Write-Verbose "Create results file [$outputFilePath]" -} +} \ No newline at end of file diff --git a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 index a2ac22d565..d975dea940 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/module.tests.ps1 @@ -3,7 +3,7 @@ param ( [Parameter(Mandatory = $false)] [array] $moduleFolderPaths = ((Get-ChildItem $repoRootPath -Recurse -Directory -Force).FullName | Where-Object { - (Get-ChildItem $_ -File -Depth 0 -Include @('main.bicep') -Force).Count -gt 0 + (Get-ChildItem $_ -File -Depth 0 -Include @('main.json', 'main.bicep') -Force).Count -gt 0 }), [Parameter(Mandatory = $false)] @@ -27,6 +27,7 @@ $script:convertedTemplates = @{} # Shared exception messages $script:bicepTemplateCompilationFailedException = "Unable to compile the main.bicep template's content. This can happen if there is an error in the template. Please check if you can run the command ``bicep build {0} --stdout | ConvertFrom-Json -AsHashtable``." # -f $templateFilePath +$script:jsonTemplateLoadFailedException = "Unable to load the main.json template's content. This can happen if there is an error in the template. Please check if you can run the command `Get-Content {0} -Raw | ConvertFrom-Json -AsHashtable`." # -f $templateFilePath $script:templateNotFoundException = 'No template file found in folder [{0}]' # -f $moduleFolderPath # Import any helper function used in this test script @@ -202,6 +203,13 @@ Describe 'Module tests' -Tag 'Module' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'main.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } } else { throw ($templateNotFoundException -f $moduleFolderPath) } @@ -331,6 +339,13 @@ Describe 'Module tests' -Tag 'Module' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'main.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } } else { throw ($templateNotFoundException -f $moduleFolderPath) } @@ -820,6 +835,7 @@ Describe 'Module tests' -Tag 'Module' { $incorrectOutputs | Should -BeNullOrEmpty } + # Update to work with nullable parameters It '[] All non-required parameters in template file should not have description that start with "Required.".' -TestCases $deploymentFolderTestCases { param ( [hashtable[]] $testFileTestCases, @@ -858,6 +874,13 @@ Describe 'Module tests' -Tag 'Module' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'main.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } } else { throw ($templateNotFoundException -f $moduleFolderPath) } @@ -907,184 +930,6 @@ Describe 'Module tests' -Tag 'Module' { $templateFileContent.metadata.owner | Should -Not -BeNullOrEmpty } } - - Context 'User-defined-types tests' -Tag 'UDT' { - - $udtTestCases = [System.Collections.ArrayList] @() # General UDT tests (e.g. param should exist) - $udtSpecificTestCases = [System.Collections.ArrayList] @() # Specific UDT test cases for singular UDTs (e.g. tags) - foreach ($moduleFolderPath in $moduleFolderPaths) { - - $resourceTypeIdentifier = ($moduleFolderPath -split '[\/|\\]{1}avm[\/|\\]{1}(res|ptn)[\/|\\]{1}')[2] -replace '\\', '/' # avm/res// - - # For runtime purposes, we cache the compiled template in a hashtable that uses a formatted relative module path as a key - $moduleFolderPathKey = $moduleFolderPath.Replace('\', '/').Split('/avm/')[1].Trim('/').Replace('/', '-') - if (-not ($convertedTemplates.Keys -contains $moduleFolderPathKey)) { - if (Test-Path (Join-Path $moduleFolderPath 'main.bicep')) { - $templateFilePath = Join-Path $moduleFolderPath 'main.bicep' - $templateContent = bicep build $templateFilePath --stdout | ConvertFrom-Json -AsHashtable - - if (-not $templateContent) { - throw ($bicepTemplateCompilationFailedException -f $templateFilePath) - } - } else { - throw ($templateNotFoundException -f $moduleFolderPath) - } - $convertedTemplates[$moduleFolderPathKey] = @{ - templateContent = $templateContent - templateFilePath = $templateFilePath - } - } else { - $templateContent = $convertedTemplates[$moduleFolderPathKey].templateContent - $templateFilePath = $convertedTemplates[$moduleFolderPathKey].templateFilePath - } - - $udtSpecificTestCases += @{ - moduleFolderName = $resourceTypeIdentifier - templateFileContent = $templateContent - templateFileContentBicep = Get-Content $templateFilePath - } - - # Setting expected URL only for those that doen't have multiple different variants - $avmInterfaceSpecsTemplateBase = 'https://raw.githubusercontent.com/Azure/Azure-Verified-Modules/main/docs/static/includes/interfaces' - $avmInterfaceSpecsBase = 'https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces' - $udtCases = @( - @{ - parameterName = 'diagnosticSettings' - udtName = 'diagnosticSettingType' - link = "$avmInterfaceSpecsBase#diagnostic-settings" - } - @{ - parameterName = 'roleAssignments' - udtName = 'roleAssignmentType' - udtExpectedUrl = "$avmInterfaceSpecsTemplateBase/int.rbac.udt.schema.bicep" - link = "$avmInterfaceSpecsBase#role-assignments" - } - @{ - parameterName = 'lock' - udtName = 'lockType' - udtExpectedUrl = "$avmInterfaceSpecsTemplateBase/int.locks.udt.schema.bicep" - link = "$avmInterfaceSpecsBase#resource-locks" - } - @{ - parameterName = 'managedIdentities' - udtName = 'managedIdentitiesType' - link = "$avmInterfaceSpecsBase#managed-identities" - } - @{ - parameterName = 'privateEndpoints' - udtName = 'privateEndpointType' - link = "$avmInterfaceSpecsBase#private-endpoints" - } - @{ - parameterName = 'customerManagedKey' - udtName = 'customerManagedKeyType' - link = "$avmInterfaceSpecsBase#customer-managed-keys" - } - ) - - foreach ($udtCase in $udtCases) { - $udtTestCases += @{ - moduleFolderName = $resourceTypeIdentifier - templateFileContent = $templateContent - templateFileContentBicep = Get-Content $templateFilePath - parameterName = $udtCase.parameterName - udtName = $udtCase.udtName - expectedUdtUrl = $udtCase.udtExpectedUrl ? $udtCase.udtExpectedUrl : '' - link = $udtCase.link - } - } - } - - - It "[] If template has a parameter [], it should implement the user-defined type []" -TestCases $udtTestCases { - - param( - [hashtable] $templateFileContent, - [string[]] $templateFileContentBicep, - [string] $parameterName, - [string] $udtName, - [string] $expectedUdtUrl, - [string] $link - ) - - if ($templateFileContent.parameters.Keys -contains $parameterName) { - $templateFileContent.parameters.$parameterName.Keys | Should -Contain '$ref' -Because "the [$parameterName] parameter should use a user-defined type. For for information please review the [AVM Specs]($link)." - $templateFileContent.parameters.$parameterName.'$ref' | Should -Be "#/definitions/$udtName" -Because "the [$parameterName] parameter should use a user-defined type [$udtName]. For for information please review the [AVM Specs]($link)." - - if (-not [String]::IsNullOrEmpty($expectedUdtUrl)) { - $implementedSchemaStartIndex = $templateFileContentBicep.IndexOf("type $udtName = {") - $implementedSchemaEndIndex = $implementedSchemaStartIndex + 1 - while ($templateFileContentBicep[$implementedSchemaEndIndex] -notmatch '^\}.*' -and $implementedSchemaEndIndex -lt $templateFileContentBicep.Length) { - $implementedSchemaEndIndex++ - } - if ($implementedSchemaEndIndex -eq $templateFileContentBicep.Length) { - throw "Failed to identify [$udtName] user-defined type in template." - } - $implementedSchema = $templateFileContentBicep[$implementedSchemaStartIndex..$implementedSchemaEndIndex] - - $expectedSchemaFull = (Invoke-WebRequest -Uri $expectedUdtUrl).Content -split "\n" - $expectedSchemaStartIndex = $expectedSchemaFull.IndexOf("type $udtName = {") - $expectedSchemaEndIndex = $expectedSchemaStartIndex + 1 - while ($expectedSchemaFull[$expectedSchemaEndIndex] -notmatch '^\}.*' -and $expectedSchemaEndIndex -lt $expectedSchemaFull.Length) { - $expectedSchemaEndIndex++ - } - if ($expectedSchemaEndIndex -eq $expectedSchemaFull.Length) { - throw "Failed to identify [$udtName] user-defined type in expected schema at URL [$expectedUdtUrl]." - } - $expectedSchema = $expectedSchemaFull[$expectedSchemaStartIndex..$expectedSchemaEndIndex] - - $formattedDiff = @() - foreach ($finding in (Compare-Object $implementedSchema $expectedSchema)) { - if ($finding.SideIndicator -eq '=>') { - $formattedDiff += ('+ {0}' -f $finding.InputObject) - } elseif ($finding.SideIndicator -eq '<=') { - $formattedDiff += ('- {0}' -f $finding.InputObject) - } - } - - if ($formattedDiff.Count -gt 0) { - $warningMessage = "The implemented user-defined type is not the same as the expected user-defined type ({0}) defined in the AVM specs ({1}) and should not have diff`n{2}" -f $expectedUdtUrl, $link, ($formattedDiff | Out-String) - Write-Warning $warningMessage - - # Adding also to output to show in GitHub CI - $mdFormattedDiff = ($formattedDiff -join '
') -replace '\|', '\|' - $mdFormattedWarningMessage = "The implemented user-defined type is not the same as the expected [user-defined type]({0}) defined in the [AVM specs]({1}) and should not have diff
{2}
" -f $expectedUdtUrl, $link, $mdFormattedDiff - Write-Output @{ - Warning = $mdFormattedWarningMessage - } - } - } - } else { - Set-ItResult -Skipped -Because "the module template has no [$parameterName] parameter." - } - } - - It "[] If a UDT definition [managedIdentitiesType] exists and supports system-assigned-identities, the template should have an output for its principal ID." -TestCases $udtSpecificTestCases { - - param( - [hashtable] $templateFileContent - ) - - if ($templateFileContent.definitions.Keys -contains 'managedIdentitiesType' -and $templateFileContent.definitions.managedIdentitiesType.properties.keys -contains 'systemAssigned') { - $templateFileContent.outputs.Keys | Should -Contain 'systemAssignedMIPrincipalId' -Because 'The AVM specs require a this output. For for information please review the [AVM Specs](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces#managed-identities).' - } else { - Set-ItResult -Skipped -Because "the module template has no [managedIdentitiesType] UDT definition or does not support system-assigned-identities." - } - } - - It "[] If a parameter [tags] exists it should be nullable." -TestCases $udtSpecificTestCases { - - param( - [hashtable] $templateFileContent - ) - - if ($templateFileContent.parameters.Keys -contains 'tags') { - $templateFileContent.parameters.tags.nullable | Should -Be $true -Because 'The AVM specs require a specific format. For for information please review the [AVM Specs](https://azure.github.io/Azure-Verified-Modules/specs/shared/interfaces#tags).' - } else { - Set-ItResult -Skipped -Because "the module template has no [tags] parameter." - } - } - } } Describe 'Test file tests' -Tag 'TestTemplate' { @@ -1101,7 +946,6 @@ Describe 'Test file tests' -Tag 'TestTemplate' { $resourceTypeIdentifier = ($moduleFolderPath -split '[\/|\\]{1}avm[\/|\\]{1}(res|ptn)[\/|\\]{1}')[2] -replace '\\', '/' # avm/res// $deploymentTestFileTestCases += @{ - testName = Split-Path (Split-Path $testFilePath) -Leaf testFilePath = $testFilePath testFileContent = $testFileContent moduleFolderName = $resourceTypeIdentifier @@ -1110,79 +954,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { } } - It "[] [] Bicep test deployment files should contain a parameter [serviceShort]" -TestCases $deploymentTestFileTestCases { - - param( - [object[]] $testFileContent - ) - ($testFileContent -match "^param serviceShort string = '(.*)$") | Should -Not -BeNullOrEmpty -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*''].' - } - - It "[] [] Bicep test deployment files in a [defaults] folder should have a parameter [serviceShort] with a value ending with [min]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]defaults[\\|\/].*' }) { - - param( - [object[]] $testFileContent - ) - - if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { - $Matches[1] | Should -BeLike "*min" - } else { - Set-ItResult -Skipped -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*min''] but it doesn''t.' - } - } - - It "[] [] Bicep test deployment files in a [max] folder should have a [serviceShort] parameter with a value ending with [max]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]max[\\|\/].*' }) { - - param( - [object[]] $testFileContent - ) - - if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { - $Matches[1] | Should -BeLike "*max" - } else { - Set-ItResult -Skipped -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*max''] but it doesn''t.' - } - } - - It "[] [] Bicep test deployment files in a [waf-aligned] folder should have a [serviceShort] parameter with a value ending with [waf]" -TestCases ($deploymentTestFileTestCases | Where-Object { $_.testFilePath -match '.*[\\|\/]waf\-aligned[\\|\/].*' }) { - - param( - [object[]] $testFileContent - ) - - if (($testFileContent | Out-String) -match "param serviceShort string = '(.*)'") { - $Matches[1] | Should -BeLike "*waf" - } else { - Set-ItResult -Skipped -Because 'the module test deployment file should contain a parameter [serviceShort] using the syntax [param serviceShort string = ''*waf''] but it doesn''t.' - } - } - - It "[] [] Bicep test deployment files should contain a metadata string [name]" -TestCases $deploymentTestFileTestCases { - - param( - [object[]] $testFileContent - ) - ($testFileContent | Out-String) | Should -Match "metadata name = .+" -Because 'Test cases should contain a metadata string [name] in the format `metadata name = ''This is one hell of a test name''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' - } - - It "[] [] Bicep test deployment files should contain a metadata string [description]" -TestCases $deploymentTestFileTestCases { - - param( - [object[]] $testFileContent - ) - ($testFileContent | Out-String) | Should -Match "metadata description = .+" -Because 'Test cases should contain a metadata string [description] in the format `metadata description = ''This is one hell of a description''` to be more descriptive. If provided, the tooling will automatically inject it into the module''s readme.md file.' - } - - It "[] [] Bicep test deployment files should contain a parameter [namePrefix] with value ['#_namePrefix_#']" -TestCases $deploymentTestFileTestCases { - - param( - [object[]] $testFileContent - ) - - ($testFileContent | Out-String) | Should -Match "param namePrefix string = '#_namePrefix_#'" -Because 'The test CI needs this value to ensure that deployed resources have unique names per fork.' - } - - It "[] [] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { + It "[] Bicep test deployment files should invoke test like [`module testDeployment '../.*main.bicep' = {`]" -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1193,7 +965,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { $testIndex -ne -1 | Should -Be $true -Because 'the module test invocation should be in the expected format to allow identification.' } - It '[] [] Bicep test deployment name should contain [`-test-`].' -TestCases $deploymentTestFileTestCases { + It '[] Bicep test deployment name should contain [`-test-`].' -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1204,7 +976,7 @@ Describe 'Test file tests' -Tag 'TestTemplate' { $expectedNameFormat | Should -Be $true -Because 'the handle ''-test-'' should be part of the module test invocation''s resource name to allow identification.' } - It '[] [] Bicep test deployment should have parameter [`serviceShort`].' -TestCases $deploymentTestFileTestCases { + It '[] Bicep test deployment should have parameter [`serviceShort`].' -TestCases $deploymentTestFileTestCases { param( [object[]] $testFileContent @@ -1245,6 +1017,13 @@ Describe 'API version tests' -Tag 'ApiCheck' { if (-not $templateContent) { throw ($bicepTemplateCompilationFailedException -f $templateFilePath) } + } elseIf (Test-Path (Join-Path $moduleFolderPath 'main.json')) { + $templateFilePath = Join-Path $moduleFolderPath 'main.json' + $templateContent = Get-Content $templateFilePath -Raw | ConvertFrom-Json -AsHashtable + + if (-not $templateContent) { + throw ($jsonTemplateLoadFailedException -f $templateFilePath) + } } else { throw ($templateNotFoundException -f $moduleFolderPath) } @@ -1389,4 +1168,4 @@ Describe 'API version tests' -Tag 'ApiCheck' { } } } -} +} \ No newline at end of file From 31213359a56dd36e38e4afc6b6a9537f9534ee16 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Tue, 14 Nov 2023 09:43:39 +0100 Subject: [PATCH 22/35] Update to latest --- .../staticValidation/compliance/Set-PesterGitHubOutput.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 index 3563bc5f4f..38f43808ee 100644 --- a/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 +++ b/avm/utilities/pipelines/staticValidation/compliance/Set-PesterGitHubOutput.ps1 @@ -293,4 +293,4 @@ function Set-PesterGitHubOutput { $null = New-Item -Path $OutputFilePath -Force -Value ($fileContent | Out-String) } Write-Verbose "Create results file [$outputFilePath]" -} \ No newline at end of file +} From 3d4f5c6bef1e492cd25a6d0c334088ab8afa49b7 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Sun, 26 Nov 2023 11:18:23 +0100 Subject: [PATCH 23/35] Added pipeline to main for testing --- .../workflows/avm.platform.publish.tag.yml | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/avm.platform.publish.tag.yml diff --git a/.github/workflows/avm.platform.publish.tag.yml b/.github/workflows/avm.platform.publish.tag.yml new file mode 100644 index 0000000000..e81a3c1c78 --- /dev/null +++ b/.github/workflows/avm.platform.publish.tag.yml @@ -0,0 +1,63 @@ +name: "Publish AVM module with tag" + +on: + workflow_dispatch: + inputs: + tag: + description: "The git tag of the module to publish." + required: true + type: string + +permissions: + id-token: write + contents: read + +jobs: + job_publish_module_with_tag: + runs-on: ubuntu-latest + name: "Publish module with tag" + steps: + - name: Checkout tag + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag }} + + - name: Log in to Azure + uses: azure/login@v1 + with: + client-id: ${{ env.PUBLISH_CLIENT_ID }} + tenant-id: ${{ env.PUBLISH_TENANT_ID }} + subscription-id: ${{ env.PUBLISH_SUBSCRIPTION_ID }} + + # Adding a step to explicitly install the latest Bicep CLI because there is + # always a delay in updating Bicep CLI in the job runner environments. + - name: Install the latest Bicep CLI + shell: bash + run: | + curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64 + chmod +x ./bicep + sudo mv ./bicep /usr/local/bin/bicep + bicep --version + + - name: "Publish tagged module to public bicep registry" + uses: azure/powershell@v1 + with: + azPSVersion: "latest" + inlineScript: | + # Grouping task logs + Write-Output '::group::Publish tagged module to public bicep registry' + + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'publish' 'Publish-ModuleFromTagToPBR.ps1') + + $functionInput = @{ + ModuleReleaseTagName = '${{ github.event.inputs.tag }}' + PublicRegistryServer = ConvertTo-SecureString '${{ env.PUBLISH_REGISTRY_SERVER }}' -AsPlainText -Force + } + + Write-Verbose "Invoke function with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Publish-ModuleFromTagToPBR @functionInput -Verbose + + Write-Output '::endgroup::' \ No newline at end of file From 917a7614c603ffd3c74e81992dabcc292aa0959a Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Mon, 4 Dec 2023 10:29:17 +0100 Subject: [PATCH 24/35] TEst disable pipe --- .github/workflows/test.workflow.yml | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/test.workflow.yml diff --git a/.github/workflows/test.workflow.yml b/.github/workflows/test.workflow.yml new file mode 100644 index 0000000000..acad22ebf7 --- /dev/null +++ b/.github/workflows/test.workflow.yml @@ -0,0 +1,51 @@ +name: 'avm.platform.toggle-avm-workflows' + +on: + workflow_dispatch: + inputs: + workMode: + type: choice + description: "Enable or disable workflows" + required: true + options: + - "enable" + - "disable" + default: "disable" + includePattern: + type: string + description: "RegEx which workflows are included" + required: false + default: "avm\\.(?:res|ptn)" + excludePattern: + type: string + description: "RegEx which workflows are excluded" + required: false + default: "^$" + +jobs: + toggle-avm-workflows: + if: github.repository != 'Azure/bicep-registry-modules' + runs-on: ubuntu-latest + steps: + - name: 'Checkout' + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - env: + GH_TOKEN: ${{ github.token }} + name: ${{ inputs.workMode }} AVM workflows + shell: pwsh + run: | + $repo = "${{ github.repository_owner }}/${{ github.event.repository.name }}" + $workflows = gh workflow list --repo $repo --all --json 'name,state,id' | ConvertFrom-Json -Depth 100 + $relevantWorkflows = $workflows | Where-Object { + $_.name -match "${{ inputs.includePattern }}" -and $_.name -notmatch "${{ inputs.excludePattern }}" + } + + foreach ($workflow in $relevantWorkflows) { + if (("${{ inputs.workMode }}" -eq "disable" -and $workflow.state -eq 'active') -or ("${{ inputs.workMode }}" -eq "enable" -and $workflow.state -ne 'active')) + { + Write-Verbose "${{ inputs.workMode }} $($workflow.name)" -Verbose + gh workflow ${{ inputs.workMode }} $workflow.id --repo $repo + } + } \ No newline at end of file From feb981ece77a7c31e5e80931a993613846bfe628 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Mon, 4 Dec 2023 10:32:18 +0100 Subject: [PATCH 25/35] Update to latest --- .../workflows/avm.platform.publish.tag.yml | 63 ------------------- .github/workflows/test.workflow.yml | 51 --------------- 2 files changed, 114 deletions(-) delete mode 100644 .github/workflows/avm.platform.publish.tag.yml delete mode 100644 .github/workflows/test.workflow.yml diff --git a/.github/workflows/avm.platform.publish.tag.yml b/.github/workflows/avm.platform.publish.tag.yml deleted file mode 100644 index e81a3c1c78..0000000000 --- a/.github/workflows/avm.platform.publish.tag.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: "Publish AVM module with tag" - -on: - workflow_dispatch: - inputs: - tag: - description: "The git tag of the module to publish." - required: true - type: string - -permissions: - id-token: write - contents: read - -jobs: - job_publish_module_with_tag: - runs-on: ubuntu-latest - name: "Publish module with tag" - steps: - - name: Checkout tag - uses: actions/checkout@v4 - with: - ref: ${{ github.event.inputs.tag }} - - - name: Log in to Azure - uses: azure/login@v1 - with: - client-id: ${{ env.PUBLISH_CLIENT_ID }} - tenant-id: ${{ env.PUBLISH_TENANT_ID }} - subscription-id: ${{ env.PUBLISH_SUBSCRIPTION_ID }} - - # Adding a step to explicitly install the latest Bicep CLI because there is - # always a delay in updating Bicep CLI in the job runner environments. - - name: Install the latest Bicep CLI - shell: bash - run: | - curl -Lo bicep https://github.com/Azure/bicep/releases/latest/download/bicep-linux-x64 - chmod +x ./bicep - sudo mv ./bicep /usr/local/bin/bicep - bicep --version - - - name: "Publish tagged module to public bicep registry" - uses: azure/powershell@v1 - with: - azPSVersion: "latest" - inlineScript: | - # Grouping task logs - Write-Output '::group::Publish tagged module to public bicep registry' - - # Load used functions - . (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'publish' 'Publish-ModuleFromTagToPBR.ps1') - - $functionInput = @{ - ModuleReleaseTagName = '${{ github.event.inputs.tag }}' - PublicRegistryServer = ConvertTo-SecureString '${{ env.PUBLISH_REGISTRY_SERVER }}' -AsPlainText -Force - } - - Write-Verbose "Invoke function with" -Verbose - Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose - - Publish-ModuleFromTagToPBR @functionInput -Verbose - - Write-Output '::endgroup::' \ No newline at end of file diff --git a/.github/workflows/test.workflow.yml b/.github/workflows/test.workflow.yml deleted file mode 100644 index acad22ebf7..0000000000 --- a/.github/workflows/test.workflow.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: 'avm.platform.toggle-avm-workflows' - -on: - workflow_dispatch: - inputs: - workMode: - type: choice - description: "Enable or disable workflows" - required: true - options: - - "enable" - - "disable" - default: "disable" - includePattern: - type: string - description: "RegEx which workflows are included" - required: false - default: "avm\\.(?:res|ptn)" - excludePattern: - type: string - description: "RegEx which workflows are excluded" - required: false - default: "^$" - -jobs: - toggle-avm-workflows: - if: github.repository != 'Azure/bicep-registry-modules' - runs-on: ubuntu-latest - steps: - - name: 'Checkout' - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - env: - GH_TOKEN: ${{ github.token }} - name: ${{ inputs.workMode }} AVM workflows - shell: pwsh - run: | - $repo = "${{ github.repository_owner }}/${{ github.event.repository.name }}" - $workflows = gh workflow list --repo $repo --all --json 'name,state,id' | ConvertFrom-Json -Depth 100 - $relevantWorkflows = $workflows | Where-Object { - $_.name -match "${{ inputs.includePattern }}" -and $_.name -notmatch "${{ inputs.excludePattern }}" - } - - foreach ($workflow in $relevantWorkflows) { - if (("${{ inputs.workMode }}" -eq "disable" -and $workflow.state -eq 'active') -or ("${{ inputs.workMode }}" -eq "enable" -and $workflow.state -ne 'active')) - { - Write-Verbose "${{ inputs.workMode }} $($workflow.name)" -Verbose - gh workflow ${{ inputs.workMode }} $workflow.id --repo $repo - } - } \ No newline at end of file From f4136ecc4bc806790f908046979c3045f3cb0e5e Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 22 Dec 2023 10:47:59 +0100 Subject: [PATCH 26/35] Added SA workflow --- .../avm.res.storage.storage-account.yml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/avm.res.storage.storage-account.yml diff --git a/.github/workflows/avm.res.storage.storage-account.yml b/.github/workflows/avm.res.storage.storage-account.yml new file mode 100644 index 0000000000..061ef0be68 --- /dev/null +++ b/.github/workflows/avm.res.storage.storage-account.yml @@ -0,0 +1,83 @@ +name: "avm.res.storage.storage-account" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.storage.storage-account.yml" + - "avm/res/storage/storage-account/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/storage/storage-account" + workflowPath: ".github/workflows/avm.res.storage.storage-account.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From e55e73257d0fcf23b3c8bae557fbcf54e5ac5ea0 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Mon, 1 Jan 2024 19:15:54 +0100 Subject: [PATCH 27/35] Added workflow --- ....virtual-machine-images.image-template.yml | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 .github/workflows/avm.res.virtual-machine-images.image-template.yml diff --git a/.github/workflows/avm.res.virtual-machine-images.image-template.yml b/.github/workflows/avm.res.virtual-machine-images.image-template.yml new file mode 100644 index 0000000000..08c03c7560 --- /dev/null +++ b/.github/workflows/avm.res.virtual-machine-images.image-template.yml @@ -0,0 +1,83 @@ +name: "avm.res.resource-graph.query" + +on: + schedule: + - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) + workflow_dispatch: + inputs: + staticValidation: + type: boolean + description: "Execute static validation" + required: false + default: true + deploymentValidation: + type: boolean + description: "Execute deployment validation" + required: false + default: true + removeDeployment: + type: boolean + description: "Remove deployed module" + required: false + default: true + + push: + branches: + - main + paths: + - ".github/actions/templates/avm-**" + - ".github/workflows/avm.template.module.yml" + - ".github/workflows/avm.res.virtual-machine-images.image-template.yml" + - "avm/res/virtual-machine-images/image-template/**" + - "avm/utilities/pipelines/**" + - "!*/**/README.md" + +env: + modulePath: "avm/res/virtual-machine-images/image-template" + workflowPath: ".github/workflows/avm.res.virtual-machine-images.image-template.yml" + +concurrency: + group: ${{ github.workflow }} + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + name: "Initialize pipeline" + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: "Set input parameters to output variables" + id: get-workflow-param + uses: ./.github/actions/templates/avm-getWorkflowInput + with: + workflowPath: "${{ env.workflowPath}}" + - name: "Get module test file paths" + id: get-module-test-file-paths + uses: ./.github/actions/templates/avm-getModuleTestFiles + with: + modulePath: "${{ env.modulePath }}" + outputs: + workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} + modulePath: "${{ env.modulePath }}" + + ############################## + # Call reusable workflow # + ############################## + call-workflow-passing-data: + name: "Run" + needs: + - job_initialize_pipeline + uses: ./.github/workflows/avm.template.module.yml + with: + workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" + moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" + psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" + modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" + secrets: inherit From 5c6aa5e64d2e7f6ac3c9a7e1522ac8590b019f30 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Mon, 1 Jan 2024 19:16:30 +0100 Subject: [PATCH 28/35] Update to latest --- .../workflows/avm.res.virtual-machine-images.image-template.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/avm.res.virtual-machine-images.image-template.yml b/.github/workflows/avm.res.virtual-machine-images.image-template.yml index 08c03c7560..37bb62af5e 100644 --- a/.github/workflows/avm.res.virtual-machine-images.image-template.yml +++ b/.github/workflows/avm.res.virtual-machine-images.image-template.yml @@ -1,4 +1,4 @@ -name: "avm.res.resource-graph.query" +name: "avm.res.virtual-machine-images.image-template" on: schedule: From 5bad58a496a35dc5d61d39615e6ba760d3afadaa Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Thu, 4 Jan 2024 16:26:32 +0100 Subject: [PATCH 29/35] Raw VM module --- avm/res/compute/virtual-machine/README.md | 2577 ++++++++++ .../virtual-machine/extension/README.md | 156 + .../virtual-machine/extension/main.bicep | 77 + .../virtual-machine/extension/main.json | 160 + avm/res/compute/virtual-machine/main.bicep | 769 +++ avm/res/compute/virtual-machine/main.json | 4398 +++++++++++++++++ .../modules/nic-configuration.bicep | 153 + .../modules/protected-item.bicep | 55 + .../tests/e2e/linux.atmg/dependencies.bicep | 86 + .../tests/e2e/linux.atmg/main.test.bicep | 123 + .../e2e/linux.defaults/dependencies.bicep | 86 + .../tests/e2e/linux.defaults/main.test.bicep | 103 + .../tests/e2e/waf-aligned/dependencies.bicep | 267 + .../tests/e2e/waf-aligned/main.test.bicep | 293 ++ .../e2e/windows.defaults/dependencies.bicep | 30 + .../e2e/windows.defaults/main.test.bicep | 86 + .../tests/e2e/windows.max/dependencies.bicep | 310 ++ .../tests/e2e/windows.max/main.test.bicep | 331 ++ .../e2e/windows.ssecmk/dependencies.bicep | 92 + .../tests/e2e/windows.ssecmk/main.test.bicep | 105 + avm/res/compute/virtual-machine/version.json | 7 + 21 files changed, 10264 insertions(+) create mode 100644 avm/res/compute/virtual-machine/README.md create mode 100644 avm/res/compute/virtual-machine/extension/README.md create mode 100644 avm/res/compute/virtual-machine/extension/main.bicep create mode 100644 avm/res/compute/virtual-machine/extension/main.json create mode 100644 avm/res/compute/virtual-machine/main.bicep create mode 100644 avm/res/compute/virtual-machine/main.json create mode 100644 avm/res/compute/virtual-machine/modules/nic-configuration.bicep create mode 100644 avm/res/compute/virtual-machine/modules/protected-item.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep create mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep create mode 100644 avm/res/compute/virtual-machine/version.json diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md new file mode 100644 index 0000000000..deeb7b539f --- /dev/null +++ b/avm/res/compute/virtual-machine/README.md @@ -0,0 +1,2577 @@ +# Virtual Machines `[Microsoft.Compute/virtualMachines]` + +This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Usage examples](#Usage-examples) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | +| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | +| `Microsoft.Automanage/configurationProfileAssignments` | [2021-04-30-preview](https://learn.microsoft.com/en-us/azure/templates) | +| `Microsoft.Compute/virtualMachines` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines) | +| `Microsoft.Compute/virtualMachines/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines/extensions) | +| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | +| `Microsoft.Network/networkInterfaces` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/networkInterfaces) | +| `Microsoft.Network/publicIPAddresses` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/publicIPAddresses) | +| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupFabrics/protectionContainers/protectedItems) | + +## Usage examples + +The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. + +>**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. + +>**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/virtual-machine:`. + +- [Using automanage for the VM.](#example-1-using-automanage-for-the-vm) +- [Using only defaults](#example-2-using-only-defaults) +- [WAF-aligned](#example-3-waf-aligned) +- [Using only defaults](#example-4-using-only-defaults) +- [Using large parameter set](#example-5-using-large-parameter-set) +- [Using disk encryption set for the VM.](#example-6-using-disk-encryption-set-for-the-vm) + +### Example 1: _Using automanage for the VM._ + +This instance deploys the module with registering to an automation account. + + +
+ +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: '${uniqueString(deployment().name, location)}-test-cvmlinatmg' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: '0001-com-ubuntu-server-jammy' + publisher: 'Canonical' + sku: '22_04-lts-gen2' + version: 'latest' + } + name: 'cvmlinatmg' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + subnetResourceId: '' + zones: [ + '1' + '2' + '3' + ] + } + ] + nicSuffix: '-nic-01' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_DS2_v2' + // Non-required parameters + configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + disablePasswordAuthentication: true + location: '' + publicKeys: [ + { + keyData: '' + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "localAdminUser" + }, + "imageReference": { + "value": { + "offer": "0001-com-ubuntu-server-jammy", + "publisher": "Canonical", + "sku": "22_04-lts-gen2", + "version": "latest" + } + }, + "name": { + "value": "cvmlinatmg" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "subnetResourceId": "", + "zones": [ + "1", + "2", + "3" + ] + } + ], + "nicSuffix": "-nic-01", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + ] + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + // Non-required parameters + "configurationProfile": { + "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + }, + "disablePasswordAuthentication": { + "value": true + }, + "location": { + "value": "" + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/localAdminUser/.ssh/authorized_keys" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 2: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: '${uniqueString(deployment().name, location)}-test-cvmlinmin' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: '0001-com-ubuntu-server-jammy' + publisher: 'Canonical' + sku: '22_04-lts-gen2' + version: 'latest' + } + name: 'cvmlinmin' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + caching: 'ReadWrite' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_DS2_v2' + // Non-required parameters + disablePasswordAuthentication: true + location: '' + publicKeys: [ + { + keyData: '' + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "localAdminUser" + }, + "imageReference": { + "value": { + "offer": "0001-com-ubuntu-server-jammy", + "publisher": "Canonical", + "sku": "22_04-lts-gen2", + "version": "latest" + } + }, + "name": { + "value": "cvmlinmin" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + }, + "subnetResourceId": "" + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "caching": "ReadWrite", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Linux" + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + // Non-required parameters + "disablePasswordAuthentication": { + "value": true + }, + "location": { + "value": "" + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/localAdminUser/.ssh/authorized_keys" + } + ] + } + } +} +``` + +
+

+ +### Example 3: _WAF-aligned_ + +This instance deploys the module in alignment with the best-practices of the Well-Architected Framework. + + +

+ +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: '${uniqueString(deployment().name, location)}-test-cvmwinwaf' + params: { + // Required parameters + adminUsername: 'VMAdmin' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2019-datacenter' + version: 'latest' + } + name: 'cvmwinwaf' + nicConfigurations: [ + { + deleteOption: 'Delete' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: '' + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + loadBalancerBackendAddressPools: [ + { + id: '' + } + ] + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: '' + zones: [ + '1' + '2' + '3' + ] + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + caching: 'ReadWrite' + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + // Non-required parameters + adminPassword: '' + availabilityZone: 2 + backupPolicyName: '' + backupVaultName: '' + backupVaultResourceGroup: '' + computerName: 'winvm1' + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'ReadOnly' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + enableAutomaticUpdates: true + encryptionAtHost: false + extensionAadJoinConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: 'true' + Exclusions: { + Extensions: '.ext1;.ext2' + Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' + Processes: 'excludedproc1.exe;excludedproc2.exe' + } + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: '' + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' + ResizeOSDisk: 'false' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + VolumeType: 'All' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: '' + uri: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionCustomScriptProtectedSetting: { + commandToExecute: '' + } + extensionDependencyAgentConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionDSCConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionMonitoringAgentConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionNetworkWatcherAgentConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + patchMode: 'AutomaticByPlatform' + proximityPlacementGroupResourceId: '' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "VMAdmin" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2019-datacenter", + "version": "latest" + } + }, + "name": { + "value": "cvmwinwaf" + }, + "nicConfigurations": { + "value": [ + { + "deleteOption": "Delete", + "diagnosticSettings": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ], + "ipConfigurations": [ + { + "applicationSecurityGroups": [ + { + "id": "" + } + ], + "diagnosticSettings": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ], + "loadBalancerBackendAddressPools": [ + { + "id": "" + } + ], + "name": "ipconfig01", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + }, + "subnetResourceId": "", + "zones": [ + "1", + "2", + "3" + ] + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "caching": "ReadWrite", + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "availabilityZone": { + "value": 2 + }, + "backupPolicyName": { + "value": "" + }, + "backupVaultName": { + "value": "" + }, + "backupVaultResourceGroup": { + "value": "" + }, + "computerName": { + "value": "winvm1" + }, + "dataDisks": { + "value": [ + { + "caching": "ReadOnly", + "createOption": "Empty", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "ReadOnly", + "createOption": "Empty", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "enableAutomaticUpdates": { + "value": true + }, + "encryptionAtHost": { + "value": false + }, + "extensionAadJoinConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": "true", + "Exclusions": { + "Extensions": ".ext1;.ext2", + "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", + "Processes": "excludedproc1.exe;excludedproc2.exe" + }, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "day": "7", + "isEnabled": "true", + "scanType": "Quick", + "time": "120" + } + }, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionAzureDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KekVaultResourceId": "", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", + "ResizeOSDisk": "false", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + }, + "VolumeType": "All" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "storageAccountId": "", + "uri": "" + } + ], + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionCustomScriptProtectedSetting": { + "value": { + "commandToExecute": "" + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "patchMode": { + "value": "AutomaticByPlatform" + }, + "proximityPlacementGroupResourceId": { + "value": "" + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 4: _Using only defaults_ + +This instance deploys the module with the minimum set of required parameters. + + +

+ +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: '${uniqueString(deployment().name, location)}-test-cvmwinmin' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + name: 'cvmwinmin' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + caching: 'ReadWrite' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + // Non-required parameters + adminPassword: '' + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "localAdminUser" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2022-datacenter-azure-edition", + "version": "latest" + } + }, + "name": { + "value": "cvmwinmin" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetResourceId": "" + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "caching": "ReadWrite", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "location": { + "value": "" + } + } +} +``` + +
+

+ +### Example 5: _Using large parameter set_ + +This instance deploys the module with most of its features enabled. + + +

+ +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: '${uniqueString(deployment().name, location)}-test-cvmwinmax' + params: { + // Required parameters + adminUsername: 'VMAdmin' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2019-datacenter' + version: 'latest' + } + name: 'cvmwinmax' + nicConfigurations: [ + { + deleteOption: 'Delete' + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: '' + } + ] + diagnosticSettings: [ + { + eventHubAuthorizationRuleResourceId: '' + eventHubName: '' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + name: 'customSetting' + storageAccountResourceId: '' + workspaceResourceId: '' + } + ] + loadBalancerBackendAddressPools: [ + { + id: '' + } + ] + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + } + subnetResourceId: '' + zones: [ + '1' + '2' + '3' + ] + } + ] + nicSuffix: '-nic-01' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + } + ] + osDisk: { + caching: 'ReadWrite' + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + // Non-required parameters + adminPassword: '' + availabilityZone: 2 + backupPolicyName: '' + backupVaultName: '' + backupVaultResourceGroup: '' + computerName: 'winvm1' + dataDisks: [ + { + caching: 'None' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'None' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + enableAutomaticUpdates: true + encryptionAtHost: false + extensionAadJoinConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: 'true' + Exclusions: { + Extensions: '.ext1;.ext2' + Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' + Processes: 'excludedproc1.exe;excludedproc2.exe' + } + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: '' + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' + ResizeOSDisk: 'false' + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + VolumeType: 'All' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: '' + uri: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionCustomScriptProtectedSetting: { + commandToExecute: '' + } + extensionDependencyAgentConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionDSCConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionMonitoringAgentConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + extensionNetworkWatcherAgentConfig: { + enabled: true + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } + location: '' + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + '' + ] + } + patchMode: 'AutomaticByPlatform' + proximityPlacementGroupResourceId: '' + roleAssignments: [ + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Owner' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + } + { + principalId: '' + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: '' + } + ] + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "VMAdmin" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2019-datacenter", + "version": "latest" + } + }, + "name": { + "value": "cvmwinmax" + }, + "nicConfigurations": { + "value": [ + { + "deleteOption": "Delete", + "diagnosticSettings": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ], + "ipConfigurations": [ + { + "applicationSecurityGroups": [ + { + "id": "" + } + ], + "diagnosticSettings": [ + { + "eventHubAuthorizationRuleResourceId": "", + "eventHubName": "", + "metricCategories": [ + { + "category": "AllMetrics" + } + ], + "name": "customSetting", + "storageAccountResourceId": "", + "workspaceResourceId": "" + } + ], + "loadBalancerBackendAddressPools": [ + { + "id": "" + } + ], + "name": "ipconfig01", + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "subnetResourceId": "", + "zones": [ + "1", + "2", + "3" + ] + } + ], + "nicSuffix": "-nic-01", + "roleAssignments": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + } + ] + }, + "osDisk": { + "value": { + "caching": "ReadWrite", + "createOption": "fromImage", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "availabilityZone": { + "value": 2 + }, + "backupPolicyName": { + "value": "" + }, + "backupVaultName": { + "value": "" + }, + "backupVaultResourceGroup": { + "value": "" + }, + "computerName": { + "value": "winvm1" + }, + "dataDisks": { + "value": [ + { + "caching": "None", + "createOption": "Empty", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + }, + { + "caching": "None", + "createOption": "Empty", + "deleteOption": "Delete", + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "enableAutomaticUpdates": { + "value": true + }, + "encryptionAtHost": { + "value": false + }, + "extensionAadJoinConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionAntiMalwareConfig": { + "value": { + "enabled": true, + "settings": { + "AntimalwareEnabled": "true", + "Exclusions": { + "Extensions": ".ext1;.ext2", + "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", + "Processes": "excludedproc1.exe;excludedproc2.exe" + }, + "RealtimeProtectionEnabled": "true", + "ScheduledScanSettings": { + "day": "7", + "isEnabled": "true", + "scanType": "Quick", + "time": "120" + } + }, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionAzureDiskEncryptionConfig": { + "value": { + "enabled": true, + "settings": { + "EncryptionOperation": "EnableEncryption", + "KekVaultResourceId": "", + "KeyEncryptionAlgorithm": "RSA-OAEP", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", + "ResizeOSDisk": "false", + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + }, + "VolumeType": "All" + } + } + }, + "extensionCustomScriptConfig": { + "value": { + "enabled": true, + "fileData": [ + { + "storageAccountId": "", + "uri": "" + } + ], + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionCustomScriptProtectedSetting": { + "value": { + "commandToExecute": "" + } + }, + "extensionDependencyAgentConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionDSCConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionMonitoringAgentConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "extensionNetworkWatcherAgentConfig": { + "value": { + "enabled": true, + "tags": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + }, + "location": { + "value": "" + }, + "lock": { + "value": { + "kind": "CanNotDelete", + "name": "myCustomLockName" + } + }, + "managedIdentities": { + "value": { + "systemAssigned": true, + "userAssignedResourceIds": [ + "" + ] + } + }, + "patchMode": { + "value": "AutomaticByPlatform" + }, + "proximityPlacementGroupResourceId": { + "value": "" + }, + "roleAssignments": { + "value": [ + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Owner" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" + }, + { + "principalId": "", + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "" + } + ] + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + } + } +} +``` + +
+

+ +### Example 6: _Using disk encryption set for the VM._ + +This instance deploys the module with disk enryption set. + + +

+ +via Bicep module + +```bicep +module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { + name: '${uniqueString(deployment().name, location)}-test-cvmwincmk' + params: { + // Required parameters + adminUsername: 'VMAdministrator' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2019-datacenter' + version: 'latest' + } + name: 'cvmwincmk' + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + diskEncryptionSet: { + id: '' + } + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + // Non-required parameters + adminPassword: '' + dataDisks: [ + { + diskSizeGB: '128' + managedDisk: { + diskEncryptionSet: { + id: '' + } + storageAccountType: 'Premium_LRS' + } + } + ] + location: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "adminUsername": { + "value": "VMAdministrator" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2019-datacenter", + "version": "latest" + } + }, + "name": { + "value": "cvmwincmk" + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetResourceId": "" + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "diskEncryptionSet": { + "id": "" + }, + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_DS2_v2" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "dataDisks": { + "value": [ + { + "diskSizeGB": "128", + "managedDisk": { + "diskEncryptionSet": { + "id": "" + }, + "storageAccountType": "Premium_LRS" + } + } + ] + }, + "location": { + "value": "" + } + } +} +``` + +
+

+ + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`adminUsername`](#parameter-adminusername) | securestring | Administrator username. | +| [`configurationProfile`](#parameter-configurationprofile) | string | The configuration profile of automanage. | +| [`imageReference`](#parameter-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. | +| [`name`](#parameter-name) | string | The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. | +| [`nicConfigurations`](#parameter-nicconfigurations) | array | Configures NICs and PIPs. | +| [`osDisk`](#parameter-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`](#parameter-ostype) | string | The chosen OS type. | +| [`vmSize`](#parameter-vmsize) | string | Specifies the size for the VMs. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`additionalUnattendContent`](#parameter-additionalunattendcontent) | array | Specifies additional XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied. | +| [`adminPassword`](#parameter-adminpassword) | securestring | When specifying a Windows Virtual Machine, this value should be passed. | +| [`allowExtensionOperations`](#parameter-allowextensionoperations) | bool | 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. | +| [`availabilitySetResourceId`](#parameter-availabilitysetresourceid) | string | Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set. | +| [`availabilityZone`](#parameter-availabilityzone) | int | 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`](#parameter-backuppolicyname) | string | Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. | +| [`backupVaultName`](#parameter-backupvaultname) | string | Recovery service vault name to add VMs to backup. | +| [`backupVaultResourceGroup`](#parameter-backupvaultresourcegroup) | string | Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. | +| [`bootDiagnostics`](#parameter-bootdiagnostics) | bool | Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled. | +| [`bootDiagnosticStorageAccountName`](#parameter-bootdiagnosticstorageaccountname) | string | Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided. | +| [`bootDiagnosticStorageAccountUri`](#parameter-bootdiagnosticstorageaccounturi) | string | Storage account boot diagnostic base URI. | +| [`certificatesToBeInstalled`](#parameter-certificatestobeinstalled) | array | Specifies set of certificates that should be installed onto the virtual machine. | +| [`computerName`](#parameter-computername) | string | Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name. | +| [`customData`](#parameter-customdata) | string | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | +| [`dataDisks`](#parameter-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`](#parameter-dedicatedhostid) | string | Specifies resource ID about the dedicated host that the virtual machine resides in. | +| [`disablePasswordAuthentication`](#parameter-disablepasswordauthentication) | bool | Specifies whether password authentication should be disabled. | +| [`enableAutomaticUpdates`](#parameter-enableautomaticupdates) | bool | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | +| [`enableEvictionPolicy`](#parameter-enableevictionpolicy) | bool | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | +| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | +| [`encryptionAtHost`](#parameter-encryptionathost) | bool | 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. | +| [`extensionAadJoinConfig`](#parameter-extensionaadjoinconfig) | object | The configuration for the [AAD Join] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionAntiMalwareConfig`](#parameter-extensionantimalwareconfig) | object | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionAzureDiskEncryptionConfig`](#parameter-extensionazurediskencryptionconfig) | object | The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys. | +| [`extensionCustomScriptConfig`](#parameter-extensioncustomscriptconfig) | object | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionCustomScriptProtectedSetting`](#parameter-extensioncustomscriptprotectedsetting) | secureObject | Any object that contains the extension specific protected settings. | +| [`extensionDependencyAgentConfig`](#parameter-extensiondependencyagentconfig) | object | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionDomainJoinConfig`](#parameter-extensiondomainjoinconfig) | object | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionDomainJoinPassword`](#parameter-extensiondomainjoinpassword) | securestring | Required if name is specified. Password of the user specified in user parameter. | +| [`extensionDSCConfig`](#parameter-extensiondscconfig) | object | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionMonitoringAgentConfig`](#parameter-extensionmonitoringagentconfig) | object | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`extensionNetworkWatcherAgentConfig`](#parameter-extensionnetworkwatcheragentconfig) | object | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed. | +| [`licenseType`](#parameter-licensetype) | string | 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`](#parameter-location) | string | Location for all resources. | +| [`lock`](#parameter-lock) | object | The lock settings of the service. | +| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = "True". | +| [`maxPriceForLowPriorityVm`](#parameter-maxpriceforlowpriorityvm) | string | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | +| [`patchAssessmentMode`](#parameter-patchassessmentmode) | string | VM guest patching assessment mode. Set it to 'AutomaticByPlatform' to enable automatically check for updates every 24 hours. | +| [`patchMode`](#parameter-patchmode) | string | VM guest patching orchestration mode. 'AutomaticByOS' & 'Manual' are for Windows only, 'ImageDefault' for Linux only. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'. | +| [`plan`](#parameter-plan) | 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. | +| [`priority`](#parameter-priority) | string | Specifies the priority for the virtual machine. | +| [`provisionVMAgent`](#parameter-provisionvmagent) | bool | 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. | +| [`proximityPlacementGroupResourceId`](#parameter-proximityplacementgroupresourceid) | string | Resource ID of a proximity placement group. | +| [`publicKeys`](#parameter-publickeys) | array | The list of SSH public keys used to authenticate with linux based VMs. | +| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | +| [`sasTokenValidityLength`](#parameter-sastokenvaliditylength) | string | 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`](#parameter-securebootenabled) | bool | 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`](#parameter-securitytype) | string | Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | +| [`timeZone`](#parameter-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`](#parameter-ultrassdenabled) | bool | 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. | +| [`vTpmEnabled`](#parameter-vtpmenabled) | bool | 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`](#parameter-winrm) | array | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | + +**Generated parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`baseTime`](#parameter-basetime) | string | Do not provide a value! This date value is used to generate a registration token. | + +### Parameter: `adminUsername` + +Administrator username. + +- Required: Yes +- Type: securestring + +### Parameter: `configurationProfile` + +The configuration profile of automanage. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + ] + ``` + +### Parameter: `imageReference` + +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. + +- Required: Yes +- Type: object + +### Parameter: `name` + +The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. + +- Required: Yes +- Type: string + +### Parameter: `nicConfigurations` + +Configures NICs and PIPs. + +- Required: Yes +- Type: array + +### Parameter: `osDisk` + +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. + +- Required: Yes +- Type: object + +### Parameter: `osType` + +The chosen OS type. + +- Required: Yes +- Type: string +- Allowed: + ```Bicep + [ + 'Linux' + 'Windows' + ] + ``` + +### Parameter: `vmSize` + +Specifies the size for the VMs. + +- Required: Yes +- Type: string + +### Parameter: `additionalUnattendContent` + +Specifies additional XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `adminPassword` + +When specifying a Windows Virtual Machine, this value should be passed. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `allowExtensionOperations` + +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. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `availabilitySetResourceId` + +Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `availabilityZone` + +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. + +- Required: No +- Type: int +- Default: `0` +- Allowed: + ```Bicep + [ + 0 + 1 + 2 + 3 + ] + ``` + +### Parameter: `backupPolicyName` + +Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. + +- Required: No +- Type: string +- Default: `'DefaultPolicy'` + +### Parameter: `backupVaultName` + +Recovery service vault name to add VMs to backup. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `backupVaultResourceGroup` + +Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. + +- Required: No +- Type: string +- Default: `[resourceGroup().name]` + +### Parameter: `bootDiagnostics` + +Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `bootDiagnosticStorageAccountName` + +Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `bootDiagnosticStorageAccountUri` + +Storage account boot diagnostic base URI. + +- Required: No +- Type: string +- Default: `[format('.blob.{0}/', environment().suffixes.storage)]` + +### Parameter: `certificatesToBeInstalled` + +Specifies set of certificates that should be installed onto the virtual machine. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `computerName` + +Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name. + +- Required: No +- Type: string +- Default: `[parameters('name')]` + +### Parameter: `customData` + +Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `dataDisks` + +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. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `dedicatedHostId` + +Specifies resource ID about the dedicated host that the virtual machine resides in. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `disablePasswordAuthentication` + +Specifies whether password authentication should be disabled. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableAutomaticUpdates` + +Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `enableEvictionPolicy` + +Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `enableTelemetry` + +Enable telemetry via a Globally Unique Identifier (GUID). + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `encryptionAtHost` + +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. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `extensionAadJoinConfig` + +The configuration for the [AAD Join] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionAntiMalwareConfig` + +The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionAzureDiskEncryptionConfig` + +The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionCustomScriptConfig` + +The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + fileData: [] + } + ``` + +### Parameter: `extensionCustomScriptProtectedSetting` + +Any object that contains the extension specific protected settings. + +- Required: No +- Type: secureObject +- Default: `{}` + +### Parameter: `extensionDependencyAgentConfig` + +The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionDomainJoinConfig` + +The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionDomainJoinPassword` + +Required if name is specified. Password of the user specified in user parameter. + +- Required: No +- Type: securestring +- Default: `''` + +### Parameter: `extensionDSCConfig` + +The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionMonitoringAgentConfig` + +The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `extensionNetworkWatcherAgentConfig` + +The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed. + +- Required: No +- Type: object +- Default: + ```Bicep + { + enabled: false + } + ``` + +### Parameter: `licenseType` + +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. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'Windows_Client' + 'Windows_Server' + ] + ``` + +### Parameter: `location` + +Location for all resources. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `lock` + +The lock settings of the service. + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | +| [`name`](#parameter-lockname) | string | Specify the name of lock. | + +### Parameter: `lock.kind` + +Specify the type of lock. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'CanNotDelete' + 'None' + 'ReadOnly' + ] + ``` + +### Parameter: `lock.name` + +Specify the name of lock. + +- Required: No +- Type: string + +### Parameter: `managedIdentities` + +The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = "True". + +- Required: No +- Type: object + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | +| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | + +### Parameter: `managedIdentities.systemAssigned` + +Enables system assigned managed identity on the resource. + +- Required: No +- Type: bool + +### Parameter: `managedIdentities.userAssignedResourceIds` + +The resource ID(s) to assign to the resource. + +- Required: No +- Type: array + +### Parameter: `maxPriceForLowPriorityVm` + +Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `patchAssessmentMode` + +VM guest patching assessment mode. Set it to 'AutomaticByPlatform' to enable automatically check for updates every 24 hours. + +- Required: No +- Type: string +- Default: `'ImageDefault'` +- Allowed: + ```Bicep + [ + 'AutomaticByPlatform' + 'ImageDefault' + ] + ``` + +### Parameter: `patchMode` + +VM guest patching orchestration mode. 'AutomaticByOS' & 'Manual' are for Windows only, 'ImageDefault' for Linux only. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'. + +- Required: No +- Type: string +- Default: `''` +- Allowed: + ```Bicep + [ + '' + 'AutomaticByOS' + 'AutomaticByPlatform' + 'ImageDefault' + 'Manual' + ] + ``` + +### Parameter: `plan` + +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. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `priority` + +Specifies the priority for the virtual machine. + +- Required: No +- Type: string +- Default: `'Regular'` +- Allowed: + ```Bicep + [ + 'Low' + 'Regular' + 'Spot' + ] + ``` + +### Parameter: `provisionVMAgent` + +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. + +- Required: No +- Type: bool +- Default: `True` + +### Parameter: `proximityPlacementGroupResourceId` + +Resource ID of a proximity placement group. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `publicKeys` + +The list of SSH public keys used to authenticate with linux based VMs. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `roleAssignments` + +Array of role assignments to create. + +- Required: No +- Type: array + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | +| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" | +| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | +| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | +| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | +| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | + +### Parameter: `roleAssignments.principalId` + +The principal ID of the principal (user/group/identity) to assign the role to. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.roleDefinitionIdOrName` + +The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. + +- Required: Yes +- Type: string + +### Parameter: `roleAssignments.condition` + +The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" + +- Required: No +- Type: string + +### Parameter: `roleAssignments.conditionVersion` + +Version of the condition. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + '2.0' + ] + ``` + +### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` + +The Resource Id of the delegated managed identity resource. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.description` + +The description of the role assignment. + +- Required: No +- Type: string + +### Parameter: `roleAssignments.principalType` + +The principal type of the assigned principal ID. + +- Required: No +- Type: string +- Allowed: + ```Bicep + [ + 'Device' + 'ForeignGroup' + 'Group' + 'ServicePrincipal' + 'User' + ] + ``` + +### Parameter: `sasTokenValidityLength` + +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. + +- Required: No +- Type: string +- Default: `'PT8H'` + +### Parameter: `secureBootEnabled` + +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. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `securityType` + +Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + +### Parameter: `timeZone` + +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`. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `ultraSSDEnabled` + +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. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `vTpmEnabled` + +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. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `winRM` + +Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. + +- Required: No +- Type: array +- Default: `[]` + +### Parameter: `baseTime` + +Do not provide a value! This date value is used to generate a registration token. + +- Required: No +- Type: string +- Default: `[utcNow('u')]` + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the VM. | +| `resourceGroupName` | string | The name of the resource group the VM was created in. | +| `resourceId` | string | The resource ID of the VM. | +| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/compute/virtual-machine/extension/README.md b/avm/res/compute/virtual-machine/extension/README.md new file mode 100644 index 0000000000..dccac4e45c --- /dev/null +++ b/avm/res/compute/virtual-machine/extension/README.md @@ -0,0 +1,156 @@ +# Virtual Machine Extensions `[Microsoft.Compute/virtualMachines/extensions]` + +This module deploys a Virtual Machine Extension. + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.Compute/virtualMachines/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines/extensions) | + +## Parameters + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoUpgradeMinorVersion`](#parameter-autoupgrademinorversion) | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true. | +| [`enableAutomaticUpgrade`](#parameter-enableautomaticupgrade) | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available. | +| [`name`](#parameter-name) | string | The name of the virtual machine extension. | +| [`publisher`](#parameter-publisher) | string | The name of the extension handler publisher. | +| [`type`](#parameter-type) | string | Specifies the type of the extension; an example is "CustomScriptExtension". | +| [`typeHandlerVersion`](#parameter-typehandlerversion) | string | Specifies the version of the script handler. | + +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`virtualMachineName`](#parameter-virtualmachinename) | string | The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`forceUpdateTag`](#parameter-forceupdatetag) | string | How the extension handler should be forced to update even if the extension configuration has not changed. | +| [`location`](#parameter-location) | string | The location the extension is deployed to. | +| [`protectedSettings`](#parameter-protectedsettings) | secureObject | Any object that contains the extension specific protected settings. | +| [`settings`](#parameter-settings) | object | Any object that contains the extension specific settings. | +| [`supressFailures`](#parameter-supressfailures) | bool | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false. | +| [`tags`](#parameter-tags) | object | Tags of the resource. | + +### Parameter: `autoUpgradeMinorVersion` + +Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true. + +- Required: Yes +- Type: bool + +### Parameter: `enableAutomaticUpgrade` + +Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available. + +- Required: Yes +- Type: bool + +### Parameter: `name` + +The name of the virtual machine extension. + +- Required: Yes +- Type: string + +### Parameter: `publisher` + +The name of the extension handler publisher. + +- Required: Yes +- Type: string + +### Parameter: `type` + +Specifies the type of the extension; an example is "CustomScriptExtension". + +- Required: Yes +- Type: string + +### Parameter: `typeHandlerVersion` + +Specifies the version of the script handler. + +- Required: Yes +- Type: string + +### Parameter: `virtualMachineName` + +The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment. + +- Required: Yes +- Type: string + +### Parameter: `forceUpdateTag` + +How the extension handler should be forced to update even if the extension configuration has not changed. + +- Required: No +- Type: string +- Default: `''` + +### Parameter: `location` + +The location the extension is deployed to. + +- Required: No +- Type: string +- Default: `[resourceGroup().location]` + +### Parameter: `protectedSettings` + +Any object that contains the extension specific protected settings. + +- Required: No +- Type: secureObject +- Default: `{}` + +### Parameter: `settings` + +Any object that contains the extension specific settings. + +- Required: No +- Type: object +- Default: `{}` + +### Parameter: `supressFailures` + +Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false. + +- Required: No +- Type: bool +- Default: `False` + +### Parameter: `tags` + +Tags of the resource. + +- Required: No +- Type: object + + +## Outputs + +| Output | Type | Description | +| :-- | :-- | :-- | +| `location` | string | The location the resource was deployed into. | +| `name` | string | The name of the extension. | +| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | +| `resourceId` | string | The resource ID of the extension. | + +## Cross-referenced modules + +_None_ diff --git a/avm/res/compute/virtual-machine/extension/main.bicep b/avm/res/compute/virtual-machine/extension/main.bicep new file mode 100644 index 0000000000..359f99cffd --- /dev/null +++ b/avm/res/compute/virtual-machine/extension/main.bicep @@ -0,0 +1,77 @@ +metadata name = 'Virtual Machine Extensions' +metadata description = 'This module deploys a Virtual Machine Extension.' +metadata owner = 'Azure/module-maintainers' + +@description('Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment.') +param virtualMachineName string + +@description('Required. The name of the virtual machine extension.') +param name string + +@description('Optional. The location the extension is deployed to.') +param location string = resourceGroup().location + +@description('Required. The name of the extension handler publisher.') +param publisher string + +@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension".') +param type string + +@description('Required. Specifies the version of the script handler.') +param typeHandlerVersion string + +@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true.') +param autoUpgradeMinorVersion bool + +@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed.') +param forceUpdateTag string? + +@description('Optional. Any object that contains the extension specific settings.') +param settings object? + +@description('Optional. Any object that contains the extension specific protected settings.') +@secure() +param protectedSettings object? + +@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false.') +param supressFailures bool = false + +@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available.') +param enableAutomaticUpgrade bool + +@description('Optional. Tags of the resource.') +param tags object? + +resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-11-01' existing = { + name: virtualMachineName +} + +resource extension 'Microsoft.Compute/virtualMachines/extensions@2022-11-01' = { + name: name + parent: virtualMachine + location: location + tags: tags + properties: { + publisher: publisher + type: type + typeHandlerVersion: typeHandlerVersion + autoUpgradeMinorVersion: autoUpgradeMinorVersion + enableAutomaticUpgrade: enableAutomaticUpgrade + forceUpdateTag:forceUpdateTag + settings: settings + protectedSettings: protectedSettings + suppressFailures: supressFailures + } +} + +@description('The name of the extension.') +output name string = extension.name + +@description('The resource ID of the extension.') +output resourceId string = extension.id + +@description('The name of the Resource Group the extension was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The location the resource was deployed into.') +output location string = extension.location diff --git a/avm/res/compute/virtual-machine/extension/main.json b/avm/res/compute/virtual-machine/extension/main.json new file mode 100644 index 0000000000..a078645aa8 --- /dev/null +++ b/avm/res/compute/virtual-machine/extension/main.json @@ -0,0 +1,160 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "9445653680126696241" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", + "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", + "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/virtual-machine/main.bicep b/avm/res/compute/virtual-machine/main.bicep new file mode 100644 index 0000000000..592f78b862 --- /dev/null +++ b/avm/res/compute/virtual-machine/main.bicep @@ -0,0 +1,769 @@ +metadata name = 'Virtual Machines' +metadata description = 'This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs.' +metadata owner = 'Azure/module-maintainers' + +// Main resource +@description('Required. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory.') +param name string + +@description('Optional. Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name.') +param computerName string = name + +@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 priority 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. The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = "True".') +param managedIdentities managedIdentitiesType + +@description('Optional. Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled.') +param bootDiagnostics bool = false + +@description('Optional. Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided.') +param bootDiagnosticStorageAccountName string = '' + +@description('Optional. Storage account boot diagnostic base URI.') +param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' + +@description('Optional. Resource ID of a proximity placement group.') +param proximityPlacementGroupResourceId string = '' + +@description('Optional. Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set.') +param availabilitySetResourceId 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. 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' + +// 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 name is specified. Password of the user specified in user 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 [AAD Join] extension. Must at least contain the ["enabled": true] property to be executed.') +param extensionAadJoinConfig 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. 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 [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys.') +param extensionAzureDiskEncryptionConfig 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. The lock settings of the service.') +param lock lockType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +@description('Optional. Tags of the resource.') +param tags object? + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableTelemetry 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.') +#disable-next-line secure-secrets-in-params // Not a secret +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. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') +param enableAutomaticUpdates bool = true + +@description('Optional. VM guest patching orchestration mode. \'AutomaticByOS\' & \'Manual\' are for Windows only, \'ImageDefault\' for Linux only. Refer to \'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching\'.') +@allowed([ + 'AutomaticByPlatform' + 'AutomaticByOS' + 'Manual' + 'ImageDefault' + '' +]) +param patchMode string = '' + +@description('Optional. VM guest patching assessment mode. Set it to \'AutomaticByPlatform\' to enable automatically check for updates every 24 hours.') +@allowed([ + 'AutomaticByPlatform' + 'ImageDefault' +]) +param patchAssessmentMode string = 'ImageDefault' + +@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 XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied.') +param additionalUnattendContent array = [] + +@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') +param winRM array = [] + +@description('Required. The configuration profile of automanage.') +@allowed([ + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' + '' +]) +param configurationProfile string = '' + +var publicKeysFormatted = [for publicKey in publicKeys: { + path: publicKey.path + keyData: publicKey.keyData +}] + +var linuxConfiguration = { + disablePasswordAuthentication: disablePasswordAuthentication + ssh: { + publicKeys: publicKeysFormatted + } + provisionVMAgent: provisionVMAgent + patchSettings: (provisionVMAgent && (patchMode =~ 'AutomaticByPlatform' || patchMode =~ 'ImageDefault')) ? { + patchMode: patchMode + assessmentMode: patchAssessmentMode + } : null +} + +var windowsConfiguration = { + provisionVMAgent: provisionVMAgent + enableAutomaticUpdates: enableAutomaticUpdates + patchSettings: (provisionVMAgent && (patchMode =~ 'AutomaticByPlatform' || patchMode =~ 'AutomaticByOS' || patchMode =~ 'Manual')) ? { + patchMode: patchMode + assessmentMode: patchAssessmentMode + } : null + timeZone: empty(timeZone) ? null : timeZone + additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent + winRM: !empty(winRM) ? { + listeners: winRM + } : null +} + +var accountSasProperties = { + signedServices: 'b' + signedPermission: 'r' + signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) + signedResourceTypes: 'o' + signedProtocol: 'https' +} + +var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } + +// If AADJoin Extension is enabled then we automatically enable SystemAssigned (required by AADJoin), otherwise we follow the usual logic. +var identity = !empty(managedIdentities) ? { + type: (extensionAadJoinConfig.enabled ? true : (managedIdentities.?systemAssigned ?? false)) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) + userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null +} : null + +var builtInRoleNames = { + Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') + 'Desktop Virtualization Power On Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33') + 'Desktop Virtualization Power On Off Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e') + 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c') + 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') + 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') + 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') + 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') + 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') + Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') + 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') + 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') + 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') + 'VM Scanner Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd') +} + +resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { + name: '46d3xbcp.res.compute-virtualmachine.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + outputs: { + telemetry: { + type: 'String' + value: 'For more information, see https://aka.ms/avm/TelemetryInfo' + } + } + } + } +} + +module vm_nic 'modules/nic-configuration.bicep' = [for (nicConfiguration, index) in nicConfigurations: { + name: '${uniqueString(deployment().name, location)}-VM-Nic-${index}' + params: { + networkInterfaceName: '${name}${nicConfiguration.nicSuffix}' + virtualMachineName: name + location: location + enableIPForwarding: contains(nicConfiguration, 'enableIPForwarding') ? (!empty(nicConfiguration.enableIPForwarding) ? nicConfiguration.enableIPForwarding : false) : false + enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true + dnsServers: contains(nicConfiguration, 'dnsServers') ? (!empty(nicConfiguration.dnsServers) ? nicConfiguration.dnsServers : []) : [] + networkSecurityGroupResourceId: contains(nicConfiguration, 'networkSecurityGroupResourceId') ? nicConfiguration.networkSecurityGroupResourceId : '' + ipConfigurations: nicConfiguration.ipConfigurations + lock: nicConfiguration.?lock ?? lock + tags: nicConfiguration.?tags ?? tags + diagnosticSettings: nicConfiguration.?diagnosticSettings + roleAssignments: nicConfiguration.?roleAssignments + enableTelemetry: nicConfiguration.?enableTelemetry ?? enableTelemetry + } +}] + +resource vm 'Microsoft.Compute/virtualMachines@2022-11-01' = { + name: name + location: location + identity: identity + tags: tags + zones: availabilityZone != 0 ? array(availabilityZone) : null + plan: !empty(plan) ? plan : null + properties: { + hardwareProfile: { + vmSize: vmSize + } + securityProfile: { + encryptionAtHost: encryptionAtHost ? encryptionAtHost : null + securityType: securityType + uefiSettings: securityType == 'TrustedLaunch' ? { + secureBootEnabled: secureBootEnabled + vTpmEnabled: vTpmEnabled + } : null + } + storageProfile: { + imageReference: imageReference + osDisk: { + name: '${name}-disk-os-01' + createOption: contains(osDisk, 'createOption') ? osDisk.createOption : 'FromImage' + deleteOption: contains(osDisk, 'deleteOption') ? osDisk.deleteOption : 'Delete' + diskSizeGB: osDisk.diskSizeGB + caching: contains(osDisk, 'caching') ? osDisk.caching : 'ReadOnly' + managedDisk: { + storageAccountType: osDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? { + id: osDisk.managedDisk.diskEncryptionSet.id + } : null + } + } + dataDisks: [for (dataDisk, index) in dataDisks: { + lun: index + name: '${name}-disk-data-${padLeft((index + 1), 2, '0')}' + diskSizeGB: dataDisk.diskSizeGB + createOption: contains(dataDisk, 'createOption') ? dataDisk.createOption : 'Empty' + deleteOption: contains(dataDisk, 'deleteOption') ? dataDisk.deleteOption : 'Delete' + caching: contains(dataDisk, 'caching') ? dataDisk.caching : 'ReadOnly' + managedDisk: { + storageAccountType: dataDisk.managedDisk.storageAccountType + diskEncryptionSet: contains(dataDisk.managedDisk, 'diskEncryptionSet') ? { + id: dataDisk.managedDisk.diskEncryptionSet.id + } : null + } + }] + } + additionalCapabilities: { + ultraSSDEnabled: ultraSSDEnabled + } + osProfile: { + computerName: computerName + adminUsername: adminUsername + adminPassword: adminPassword + customData: !empty(customData) ? base64(customData) : null + windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null + linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null + secrets: certificatesToBeInstalled + allowExtensionOperations: allowExtensionOperations + } + networkProfile: { + networkInterfaces: [for (nicConfiguration, index) in nicConfigurations: { + properties: { + deleteOption: contains(nicConfiguration, 'deleteOption') ? nicConfiguration.deleteOption : 'Delete' + primary: index == 0 ? true : false + } + #disable-next-line use-resource-id-functions // It's a reference from inside a loop which makes resolving it using a resource reference particulary difficult. + id: az.resourceId('Microsoft.Network/networkInterfaces', '${name}${nicConfiguration.nicSuffix}') + }] + } + diagnosticsProfile: { + bootDiagnostics: { + enabled: !empty(bootDiagnosticStorageAccountName) ? true : bootDiagnostics + storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null + } + } + availabilitySet: !empty(availabilitySetResourceId) ? { + id: availabilitySetResourceId + } : null + proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) ? { + id: proximityPlacementGroupResourceId + } : null + priority: priority + evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null + billingProfile: !empty(priority) && !empty(maxPriceForLowPriorityVm) ? { + maxPrice: maxPriceForLowPriorityVm + } : null + host: !empty(dedicatedHostId) ? { + id: dedicatedHostId + } : null + licenseType: !empty(licenseType) ? licenseType : null + } + dependsOn: [ + vm_nic + ] +} + +resource vm_configurationProfileAssignment 'Microsoft.Automanage/configurationProfileAssignments@2021-04-30-preview' = if (!empty(configurationProfile)) { + name: 'default' + properties: { + configurationProfile: configurationProfile + } + scope: vm +} + +module vm_aadJoinExtension 'extension/main.bicep' = if (extensionAadJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-AADLogin' + params: { + virtualMachineName: vm.name + name: 'AADLogin' + location: location + publisher: 'Microsoft.Azure.ActiveDirectory' + type: osType == 'Windows' ? 'AADLoginForWindows' : 'AADSSHLoginforLinux' + typeHandlerVersion: contains(extensionAadJoinConfig, 'typeHandlerVersion') ? extensionAadJoinConfig.typeHandlerVersion : '1.0' + autoUpgradeMinorVersion: contains(extensionAadJoinConfig, 'autoUpgradeMinorVersion') ? extensionAadJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAadJoinConfig, 'enableAutomaticUpgrade') ? extensionAadJoinConfig.enableAutomaticUpgrade : false + settings: contains(extensionAadJoinConfig, 'settings') ? extensionAadJoinConfig.settings : {} + tags: extensionAadJoinConfig.?tags ?? tags + } +} + +module vm_domainJoinExtension 'extension/main.bicep' = if (extensionDomainJoinConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DomainJoin' + params: { + virtualMachineName: vm.name + name: 'DomainJoin' + location: location + publisher: 'Microsoft.Compute' + type: 'JsonADDomainExtension' + typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false + settings: extensionDomainJoinConfig.settings + tags: extensionDomainJoinConfig.?tags ?? tags + protectedSettings: { + Password: extensionDomainJoinPassword + } + } +} + +module vm_microsoftAntiMalwareExtension 'extension/main.bicep' = if (extensionAntiMalwareConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-MicrosoftAntiMalware' + params: { + virtualMachineName: vm.name + name: 'MicrosoftAntiMalware' + location: location + publisher: 'Microsoft.Azure.Security' + type: 'IaaSAntimalware' + typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' + autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false + settings: extensionAntiMalwareConfig.settings + tags: extensionAntiMalwareConfig.?tags ?? tags + } +} + +// resource vm_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { +// name: last(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : 'law'), '/'))! +// scope: az.resourceGroup(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '//'), '/')[2], split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '////'), '/')[4]) +// } + +module vm_azureMonitoringAgentExtension 'extension/main.bicep' = if (extensionMonitoringAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-AzureMonitoringAgent' + params: { + virtualMachineName: vm.name + name: 'AzureMonitoringAgent' + location: location + publisher: 'Microsoft.Azure.Monitor' + type: osType == 'Windows' ? 'AzureMonitorWindowsAgent' : 'AzureMonitorLinuxAgent' + typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.21') + autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : true + tags: extensionMonitoringAgentConfig.?tags ?? tags + } +} + +module vm_dependencyAgentExtension 'extension/main.bicep' = if (extensionDependencyAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DependencyAgent' + params: { + virtualMachineName: vm.name + name: 'DependencyAgent' + location: location + publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' + type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' + typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' + autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true + tags: extensionDependencyAgentConfig.?tags ?? tags + } +} + +module vm_networkWatcherAgentExtension 'extension/main.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-NetworkWatcherAgent' + params: { + virtualMachineName: vm.name + name: 'NetworkWatcherAgent' + location: location + publisher: 'Microsoft.Azure.NetworkWatcher' + type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' + typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' + autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false + tags: extensionNetworkWatcherAgentConfig.?tags ?? tags + } +} + +module vm_desiredStateConfigurationExtension 'extension/main.bicep' = if (extensionDSCConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-DesiredStateConfiguration' + params: { + virtualMachineName: vm.name + name: 'DesiredStateConfiguration' + location: location + publisher: 'Microsoft.Powershell' + type: 'DSC' + typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' + autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false + settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} + tags: extensionDSCConfig.?tags ?? tags + protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} + } +} + +module vm_customScriptExtension 'extension/main.bicep' = if (extensionCustomScriptConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-CustomScriptExtension' + params: { + virtualMachineName: vm.name + name: 'CustomScriptExtension' + location: location + publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' + type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' + typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') + autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false + settings: { + fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] + } + tags: extensionCustomScriptConfig.?tags ?? tags + protectedSettings: extensionCustomScriptProtectedSetting + } + dependsOn: [ + vm_desiredStateConfigurationExtension + ] +} + +module vm_azureDiskEncryptionExtension 'extension/main.bicep' = if (extensionAzureDiskEncryptionConfig.enabled) { + name: '${uniqueString(deployment().name, location)}-VM-AzureDiskEncryption' + params: { + virtualMachineName: vm.name + name: 'AzureDiskEncryption' + location: location + publisher: 'Microsoft.Azure.Security' + type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' + typeHandlerVersion: contains(extensionAzureDiskEncryptionConfig, 'typeHandlerVersion') ? extensionAzureDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') + autoUpgradeMinorVersion: contains(extensionAzureDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionAzureDiskEncryptionConfig.autoUpgradeMinorVersion : true + enableAutomaticUpgrade: contains(extensionAzureDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionAzureDiskEncryptionConfig.enableAutomaticUpgrade : false + forceUpdateTag: contains(extensionAzureDiskEncryptionConfig, 'forceUpdateTag') ? extensionAzureDiskEncryptionConfig.forceUpdateTag : '1.0' + settings: extensionAzureDiskEncryptionConfig.settings + tags: extensionAzureDiskEncryptionConfig.?tags ?? tags + } + dependsOn: [ + vm_customScriptExtension + vm_azureMonitoringAgentExtension + ] +} + +module vm_backup 'modules/protected-item.bicep' = if (!empty(backupVaultName)) { + name: '${uniqueString(deployment().name, location)}-VM-Backup' + params: { + name: 'vm;iaasvmcontainerv2;${resourceGroup().name};${vm.name}' + location: location + policyId: az.resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', backupVaultName, backupPolicyName) + protectedItemType: 'Microsoft.Compute/virtualMachines' + protectionContainerName: 'iaasvmcontainer;iaasvmcontainerv2;${resourceGroup().name};${vm.name}' + recoveryVaultName: backupVaultName + sourceResourceId: vm.id + } + scope: az.resourceGroup(backupVaultResourceGroup) + dependsOn: [ + vm_aadJoinExtension + vm_domainJoinExtension + vm_azureMonitoringAgentExtension + vm_microsoftAntiMalwareExtension + vm_networkWatcherAgentExtension + vm_dependencyAgentExtension + vm_desiredStateConfigurationExtension + vm_customScriptExtension + ] +} + +resource vm_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { + name: lock.?name ?? 'lock-${name}' + properties: { + level: lock.?kind ?? '' + notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.' + } + scope: vm +} + +resource vm_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { + name: guid(vm.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) + properties: { + roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) + principalId: roleAssignment.principalId + description: roleAssignment.?description + principalType: roleAssignment.?principalType + condition: roleAssignment.?condition + conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set + delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId + } + scope: vm +}] + +@description('The name of the VM.') +output name string = vm.name + +@description('The resource ID of the VM.') +output resourceId string = vm.id + +@description('The name of the resource group the VM was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The principal ID of the system assigned identity.') +output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(vm.identity, 'principalId') ? vm.identity.principalId : '' + +@description('The location the resource was deployed into.') +output location string = vm.location + +// =============== // +// Definitions // +// =============== // + +type managedIdentitiesType = { + @description('Optional. Enables system assigned managed identity on the resource.') + systemAssigned: bool? + + @description('Optional. The resource ID(s) to assign to the resource.') + userAssignedResourceIds: string[]? +}? + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + logCategoriesAndGroups: { + @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.') + categoryGroup: string? + }[]? + + @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to \'\' to disable metric collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') + category: string + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + workspaceResourceId: string? + + @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + storageAccountResourceId: 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.') + eventHubAuthorizationRuleResourceId: 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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? diff --git a/avm/res/compute/virtual-machine/main.json b/avm/res/compute/virtual-machine/main.json new file mode 100644 index 0000000000..9f8f0c17f3 --- /dev/null +++ b/avm/res/compute/virtual-machine/main.json @@ -0,0 +1,4398 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "3906813880748579145" + }, + "name": "Virtual Machines", + "description": "This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "managedIdentitiesType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource." + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory." + } + }, + "computerName": { + "type": "string", + "defaultValue": "[parameters('name')]", + "metadata": { + "description": "Optional. Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name." + } + }, + "vmSize": { + "type": "string", + "metadata": { + "description": "Required. Specifies the size for the VMs." + } + }, + "encryptionAtHost": { + "type": "bool", + "defaultValue": true, + "metadata": { + "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." + } + }, + "securityType": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings." + } + }, + "secureBootEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "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." + } + }, + "vTpmEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "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." + } + }, + "imageReference": { + "type": "object", + "metadata": { + "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." + } + }, + "plan": { + "type": "object", + "defaultValue": {}, + "metadata": { + "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." + } + }, + "osDisk": { + "type": "object", + "metadata": { + "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." + } + }, + "dataDisks": { + "type": "array", + "defaultValue": [], + "metadata": { + "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." + } + }, + "ultraSSDEnabled": { + "type": "bool", + "defaultValue": false, + "metadata": { + "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." + } + }, + "adminUsername": { + "type": "securestring", + "metadata": { + "description": "Required. Administrator username." + } + }, + "adminPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed." + } + }, + "customData": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format." + } + }, + "certificatesToBeInstalled": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies set of certificates that should be installed onto the virtual machine." + } + }, + "priority": { + "type": "string", + "defaultValue": "Regular", + "allowedValues": [ + "Regular", + "Low", + "Spot" + ], + "metadata": { + "description": "Optional. Specifies the priority for the virtual machine." + } + }, + "enableEvictionPolicy": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy." + } + }, + "maxPriceForLowPriorityVm": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars." + } + }, + "dedicatedHostId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Specifies resource ID about the dedicated host that the virtual machine resides in." + } + }, + "licenseType": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "Windows_Client", + "Windows_Server", + "" + ], + "metadata": { + "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." + } + }, + "publicKeys": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. The list of SSH public keys used to authenticate with linux based VMs." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentitiesType", + "metadata": { + "description": "Optional. The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = \"True\"." + } + }, + "bootDiagnostics": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled." + } + }, + "bootDiagnosticStorageAccountName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided." + } + }, + "bootDiagnosticStorageAccountUri": { + "type": "string", + "defaultValue": "[format('.blob.{0}/', environment().suffixes.storage)]", + "metadata": { + "description": "Optional. Storage account boot diagnostic base URI." + } + }, + "proximityPlacementGroupResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of a proximity placement group." + } + }, + "availabilitySetResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set." + } + }, + "availabilityZone": { + "type": "int", + "defaultValue": 0, + "allowedValues": [ + 0, + 1, + 2, + 3 + ], + "metadata": { + "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." + } + }, + "nicConfigurations": { + "type": "array", + "metadata": { + "description": "Required. Configures NICs and PIPs." + } + }, + "backupVaultName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. Recovery service vault name to add VMs to backup." + } + }, + "backupVaultResourceGroup": { + "type": "string", + "defaultValue": "[resourceGroup().name]", + "metadata": { + "description": "Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default." + } + }, + "backupPolicyName": { + "type": "string", + "defaultValue": "DefaultPolicy", + "metadata": { + "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." + } + }, + "allowExtensionOperations": { + "type": "bool", + "defaultValue": true, + "metadata": { + "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." + } + }, + "extensionDomainJoinPassword": { + "type": "securestring", + "defaultValue": "", + "metadata": { + "description": "Optional. Required if name is specified. Password of the user specified in user parameter." + } + }, + "extensionDomainJoinConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Domain Join] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionAadJoinConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [AAD Join] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionAntiMalwareConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Anti Malware] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionMonitoringAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionDependencyAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Dependency Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionNetworkWatcherAgentConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionAzureDiskEncryptionConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Azure Disk Encryption] extension. Must at least contain the [\"enabled\": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys." + } + }, + "extensionDSCConfig": { + "type": "object", + "defaultValue": { + "enabled": false + }, + "metadata": { + "description": "Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionCustomScriptConfig": { + "type": "object", + "defaultValue": { + "enabled": false, + "fileData": [] + }, + "metadata": { + "description": "Optional. The configuration for the [Custom Script] extension. Must at least contain the [\"enabled\": true] property to be executed." + } + }, + "extensionCustomScriptProtectedSetting": { + "type": "secureObject", + "defaultValue": {}, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + }, + "baseTime": { + "type": "string", + "defaultValue": "[utcNow('u')]", + "metadata": { + "description": "Generated. Do not provide a value! This date value is used to generate a registration token." + } + }, + "sasTokenValidityLength": { + "type": "string", + "defaultValue": "PT8H", + "metadata": { + "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." + } + }, + "osType": { + "type": "string", + "allowedValues": [ + "Windows", + "Linux" + ], + "metadata": { + "description": "Required. The chosen OS type." + } + }, + "disablePasswordAuthentication": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Specifies whether password authentication should be disabled." + } + }, + "provisionVMAgent": { + "type": "bool", + "defaultValue": true, + "metadata": { + "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." + } + }, + "enableAutomaticUpdates": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning." + } + }, + "patchMode": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "AutomaticByPlatform", + "AutomaticByOS", + "Manual", + "ImageDefault", + "" + ], + "metadata": { + "description": "Optional. VM guest patching orchestration mode. 'AutomaticByOS' & 'Manual' are for Windows only, 'ImageDefault' for Linux only. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'." + } + }, + "patchAssessmentMode": { + "type": "string", + "defaultValue": "ImageDefault", + "allowedValues": [ + "AutomaticByPlatform", + "ImageDefault" + ], + "metadata": { + "description": "Optional. VM guest patching assessment mode. Set it to 'AutomaticByPlatform' to enable automatically check for updates every 24 hours." + } + }, + "timeZone": { + "type": "string", + "defaultValue": "", + "metadata": { + "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`." + } + }, + "additionalUnattendContent": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies additional XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied." + } + }, + "winRM": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object." + } + }, + "configurationProfile": { + "type": "string", + "defaultValue": "", + "allowedValues": [ + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", + "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest", + "" + ], + "metadata": { + "description": "Required. The configuration profile of automanage." + } + } + }, + "variables": { + "copy": [ + { + "name": "publicKeysFormatted", + "count": "[length(parameters('publicKeys'))]", + "input": { + "path": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].path]", + "keyData": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].keyData]" + } + } + ], + "linuxConfiguration": { + "disablePasswordAuthentication": "[parameters('disablePasswordAuthentication')]", + "ssh": { + "publicKeys": "[variables('publicKeysFormatted')]" + }, + "provisionVMAgent": "[parameters('provisionVMAgent')]", + "patchSettings": "[if(and(parameters('provisionVMAgent'), or(equals(toLower(parameters('patchMode')), toLower('AutomaticByPlatform')), equals(toLower(parameters('patchMode')), toLower('ImageDefault')))), createObject('patchMode', parameters('patchMode'), 'assessmentMode', parameters('patchAssessmentMode')), null())]" + }, + "windowsConfiguration": { + "provisionVMAgent": "[parameters('provisionVMAgent')]", + "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", + "patchSettings": "[if(and(parameters('provisionVMAgent'), or(or(equals(toLower(parameters('patchMode')), toLower('AutomaticByPlatform')), equals(toLower(parameters('patchMode')), toLower('AutomaticByOS'))), equals(toLower(parameters('patchMode')), toLower('Manual')))), createObject('patchMode', parameters('patchMode'), 'assessmentMode', parameters('patchAssessmentMode')), null())]", + "timeZone": "[if(empty(parameters('timeZone')), null(), parameters('timeZone'))]", + "additionalUnattendContent": "[if(empty(parameters('additionalUnattendContent')), null(), parameters('additionalUnattendContent'))]", + "winRM": "[if(not(empty(parameters('winRM'))), createObject('listeners', parameters('winRM')), null())]" + }, + "accountSasProperties": { + "signedServices": "b", + "signedPermission": "r", + "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", + "signedResourceTypes": "o", + "signedProtocol": "https" + }, + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(if(parameters('extensionAadJoinConfig').enabled, true(), coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false())), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Data Operator for Managed Disks": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e')]", + "Desktop Virtualization Power On Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33')]", + "Desktop Virtualization Power On Off Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e')]", + "Desktop Virtualization Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c')]", + "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", + "Disk Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24')]", + "Disk Pool Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840')]", + "Disk Restore Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13')]", + "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", + "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", + "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", + "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", + "VM Scanner Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.compute-virtualmachine.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "vm": { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "identity": "[variables('identity')]", + "tags": "[parameters('tags')]", + "zones": "[if(not(equals(parameters('availabilityZone'), 0)), array(parameters('availabilityZone')), null())]", + "plan": "[if(not(empty(parameters('plan'))), parameters('plan'), null())]", + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "securityProfile": { + "encryptionAtHost": "[if(parameters('encryptionAtHost'), parameters('encryptionAtHost'), null())]", + "securityType": "[parameters('securityType')]", + "uefiSettings": "[if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())]" + }, + "storageProfile": { + "copy": [ + { + "name": "dataDisks", + "count": "[length(parameters('dataDisks'))]", + "input": { + "lun": "[copyIndex('dataDisks')]", + "name": "[format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0'))]", + "diskSizeGB": "[parameters('dataDisks')[copyIndex('dataDisks')].diskSizeGB]", + "createOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'createOption'), parameters('dataDisks')[copyIndex('dataDisks')].createOption, 'Empty')]", + "deleteOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'deleteOption'), parameters('dataDisks')[copyIndex('dataDisks')].deleteOption, 'Delete')]", + "caching": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'caching'), parameters('dataDisks')[copyIndex('dataDisks')].caching, 'ReadOnly')]", + "managedDisk": { + "storageAccountType": "[parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')].managedDisk, 'diskEncryptionSet'), createObject('id', parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.diskEncryptionSet.id), null())]" + } + } + } + ], + "imageReference": "[parameters('imageReference')]", + "osDisk": { + "name": "[format('{0}-disk-os-01', parameters('name'))]", + "createOption": "[if(contains(parameters('osDisk'), 'createOption'), parameters('osDisk').createOption, 'FromImage')]", + "deleteOption": "[if(contains(parameters('osDisk'), 'deleteOption'), parameters('osDisk').deleteOption, 'Delete')]", + "diskSizeGB": "[parameters('osDisk').diskSizeGB]", + "caching": "[if(contains(parameters('osDisk'), 'caching'), parameters('osDisk').caching, 'ReadOnly')]", + "managedDisk": { + "storageAccountType": "[parameters('osDisk').managedDisk.storageAccountType]", + "diskEncryptionSet": "[if(contains(parameters('osDisk').managedDisk, 'diskEncryptionSet'), createObject('id', parameters('osDisk').managedDisk.diskEncryptionSet.id), null())]" + } + } + }, + "additionalCapabilities": { + "ultraSSDEnabled": "[parameters('ultraSSDEnabled')]" + }, + "osProfile": { + "computerName": "[parameters('computerName')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]", + "customData": "[if(not(empty(parameters('customData'))), base64(parameters('customData')), null())]", + "windowsConfiguration": "[if(equals(parameters('osType'), 'Windows'), variables('windowsConfiguration'), null())]", + "linuxConfiguration": "[if(equals(parameters('osType'), 'Linux'), variables('linuxConfiguration'), null())]", + "secrets": "[parameters('certificatesToBeInstalled')]", + "allowExtensionOperations": "[parameters('allowExtensionOperations')]" + }, + "networkProfile": { + "copy": [ + { + "name": "networkInterfaces", + "count": "[length(parameters('nicConfigurations'))]", + "input": { + "properties": { + "deleteOption": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaces')], 'deleteOption'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].deleteOption, 'Delete')]", + "primary": "[if(equals(copyIndex('networkInterfaces'), 0), true(), false())]" + }, + "id": "[resourceId('Microsoft.Network/networkInterfaces', format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].nicSuffix))]" + } + } + ] + }, + "diagnosticsProfile": { + "bootDiagnostics": { + "enabled": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), true(), parameters('bootDiagnostics'))]", + "storageUri": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), format('https://{0}{1}', parameters('bootDiagnosticStorageAccountName'), parameters('bootDiagnosticStorageAccountUri')), null())]" + } + }, + "availabilitySet": "[if(not(empty(parameters('availabilitySetResourceId'))), createObject('id', parameters('availabilitySetResourceId')), null())]", + "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupResourceId'))), createObject('id', parameters('proximityPlacementGroupResourceId')), null())]", + "priority": "[parameters('priority')]", + "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", + "billingProfile": "[if(and(not(empty(parameters('priority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), createObject('maxPrice', parameters('maxPriceForLowPriorityVm')), null())]", + "host": "[if(not(empty(parameters('dedicatedHostId'))), createObject('id', parameters('dedicatedHostId')), null())]", + "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]" + }, + "dependsOn": [ + "vm_nic" + ] + }, + "vm_configurationProfileAssignment": { + "condition": "[not(empty(parameters('configurationProfile')))]", + "type": "Microsoft.Automanage/configurationProfileAssignments", + "apiVersion": "2021-04-30-preview", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", + "name": "default", + "properties": { + "configurationProfile": "[parameters('configurationProfile')]" + }, + "dependsOn": [ + "vm" + ] + }, + "vm_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "vm" + ] + }, + "vm_roleAssignments": { + "copy": { + "name": "vm_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "vm" + ] + }, + "vm_nic": { + "copy": { + "name": "vm_nic", + "count": "[length(parameters('nicConfigurations'))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-Nic-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "networkInterfaceName": { + "value": "[format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex()].nicSuffix)]" + }, + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "enableIPForwarding": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableIPForwarding'), if(not(empty(parameters('nicConfigurations')[copyIndex()].enableIPForwarding)), createObject('value', parameters('nicConfigurations')[copyIndex()].enableIPForwarding), createObject('value', false())), createObject('value', false()))]", + "enableAcceleratedNetworking": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableAcceleratedNetworking'), createObject('value', parameters('nicConfigurations')[copyIndex()].enableAcceleratedNetworking), createObject('value', true()))]", + "dnsServers": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'dnsServers'), if(not(empty(parameters('nicConfigurations')[copyIndex()].dnsServers)), createObject('value', parameters('nicConfigurations')[copyIndex()].dnsServers), createObject('value', createArray())), createObject('value', createArray()))]", + "networkSecurityGroupResourceId": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'networkSecurityGroupResourceId'), createObject('value', parameters('nicConfigurations')[copyIndex()].networkSecurityGroupResourceId), createObject('value', ''))]", + "ipConfigurations": { + "value": "[parameters('nicConfigurations')[copyIndex()].ipConfigurations]" + }, + "lock": { + "value": "[coalesce(tryGet(parameters('nicConfigurations')[copyIndex()], 'lock'), parameters('lock'))]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('nicConfigurations')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "diagnosticSettings": { + "value": "[tryGet(parameters('nicConfigurations')[copyIndex()], 'diagnosticSettings')]" + }, + "roleAssignments": { + "value": "[tryGet(parameters('nicConfigurations')[copyIndex()], 'roleAssignments')]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(parameters('nicConfigurations')[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "18013796946460477676" + } + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \u0007llLogs to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to AllMetrics to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "networkInterfaceName": { + "type": "string" + }, + "virtualMachineName": { + "type": "string" + }, + "location": { + "type": "string" + }, + "tags": { + "type": "object", + "nullable": true + }, + "enableIPForwarding": { + "type": "bool", + "defaultValue": false + }, + "enableAcceleratedNetworking": { + "type": "bool", + "defaultValue": false + }, + "dnsServers": { + "type": "array", + "defaultValue": [] + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." + } + }, + "networkSecurityGroupResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The network security group (NSG) to attach to the network interface." + } + }, + "ipConfigurations": { + "type": "array" + }, + "lock": { + "$ref": "#/definitions/lockType" + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the Network Interface." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "resources": { + "networkInterface_publicIPAddresses": { + "copy": { + "name": "networkInterface_publicIPAddresses", + "count": "[length(parameters('ipConfigurations'))]" + }, + "condition": "[contains(parameters('ipConfigurations')[copyIndex()], 'pipconfiguration')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-publicIP-{1}', deployment().name, copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurations')[copyIndex()].pipconfiguration.publicIpNameSuffix)]" + }, + "diagnosticSettings": { + "value": "[tryGet(parameters('ipConfigurations')[copyIndex()], 'diagnosticSettings')]" + }, + "location": { + "value": "[parameters('location')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "publicIPAddressVersion": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'publicIPAddressVersion'), createObject('value', parameters('ipConfigurations')[copyIndex()].publicIPAddressVersion), createObject('value', 'IPv4'))]", + "publicIPAllocationMethod": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'publicIPAllocationMethod'), createObject('value', parameters('ipConfigurations')[copyIndex()].publicIPAllocationMethod), createObject('value', 'Static'))]", + "publicIpPrefixResourceId": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'publicIPPrefixResourceId'), createObject('value', parameters('ipConfigurations')[copyIndex()].publicIPPrefixResourceId), createObject('value', ''))]", + "roleAssignments": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'roleAssignments'), createObject('value', parameters('ipConfigurations')[copyIndex()].roleAssignments), createObject('value', createArray()))]", + "skuName": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'skuName'), createObject('value', parameters('ipConfigurations')[copyIndex()].skuName), createObject('value', 'Standard'))]", + "skuTier": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'skuTier'), createObject('value', parameters('ipConfigurations')[copyIndex()].skuTier), createObject('value', 'Regional'))]", + "tags": { + "value": "[coalesce(tryGet(parameters('ipConfigurations')[copyIndex()], 'tags'), parameters('tags'))]" + }, + "zones": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'zones'), createObject('value', parameters('ipConfigurations')[copyIndex()].zones), createObject('value', createArray('1', '2', '3')))]", + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "3488076626994379707" + }, + "name": "Public IP Addresses", + "description": "This module deploys a Public IP Address.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, + "dnsSettingsType": { + "type": "object", + "properties": { + "domainNameLabel": { + "type": "string", + "metadata": { + "description": "Required. The domain name label. The concatenation of the domain name label and the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." + } + }, + "domainNameLabelScope": { + "type": "string", + "allowedValues": [ + "", + "NoReuse", + "ResourceGroupReuse", + "SubscriptionReuse", + "TenantReuse" + ], + "metadata": { + "description": "Required. The domain name label scope. If a domain name label and a domain name label scope are specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system with a hashed value includes in FQDN." + } + }, + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Fully Qualified Domain Name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone." + } + }, + "reverseFqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The reverse FQDN. A user-visible, fully qualified domain name that resolves to this public IP address. If the reverseFqdn is specified, then a PTR DNS record is created pointing from the IP address in the in-addr.arpa domain to the reverse FQDN." + } + } + } + }, + "ddosSettingsType": { + "type": "object", + "properties": { + "ddosProtectionPlan": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + }, + "metadata": { + "description": "Required. The DDoS protection plan ID associated with the public IP address." + } + }, + "protectionMode": { + "type": "string", + "allowedValues": [ + "Enabled" + ], + "metadata": { + "description": "Required. The DDoS protection policy customizations." + } + } + } + }, + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Public IP Address." + } + }, + "publicIpPrefixResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix." + } + }, + "publicIPAllocationMethod": { + "type": "string", + "defaultValue": "Static", + "allowedValues": [ + "Dynamic", + "Static" + ], + "metadata": { + "description": "Optional. The public IP address allocation method." + } + }, + "zones": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." + } + }, + "publicIPAddressVersion": { + "type": "string", + "defaultValue": "IPv4", + "allowedValues": [ + "IPv4", + "IPv6" + ], + "metadata": { + "description": "Optional. IP address version." + } + }, + "dnsSettings": { + "$ref": "#/definitions/dnsSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DNS settings of the public IP address." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "skuName": { + "type": "string", + "defaultValue": "Standard", + "allowedValues": [ + "Basic", + "Standard" + ], + "metadata": { + "description": "Optional. Name of a public IP address SKU." + } + }, + "skuTier": { + "type": "string", + "defaultValue": "Regional", + "allowedValues": [ + "Global", + "Regional" + ], + "metadata": { + "description": "Optional. Tier of a public IP address SKU." + } + }, + "ddosSettings": { + "$ref": "#/definitions/ddosSettingsType", + "nullable": true, + "metadata": { + "description": "Optional. The DDoS protection plan configuration associated with the public IP address." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "idleTimeoutInMinutes": { + "type": "int", + "defaultValue": 4, + "metadata": { + "description": "Optional. The idle timeout of the public IP address." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", + "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.2.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "publicIpAddress": { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "sku": { + "name": "[parameters('skuName')]", + "tier": "[parameters('skuTier')]" + }, + "zones": "[parameters('zones')]", + "properties": { + "ddosSettings": "[parameters('ddosSettings')]", + "dnsSettings": "[parameters('dnsSettings')]", + "publicIPAddressVersion": "[parameters('publicIPAddressVersion')]", + "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", + "publicIPPrefix": "[if(not(empty(parameters('publicIpPrefixResourceId'))), createObject('id', parameters('publicIpPrefixResourceId')), null())]", + "idleTimeoutInMinutes": "[parameters('idleTimeoutInMinutes')]", + "ipTags": [] + } + }, + "publicIpAddress_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + }, + "publicIpAddress_roleAssignments": { + "copy": { + "name": "publicIpAddress_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/publicIPAddresses', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + }, + "publicIpAddress_diagnosticSettings": { + "copy": { + "name": "publicIpAddress_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs', 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "publicIpAddress" + ] + } + }, + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group the public IP address was deployed into." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the public IP address." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the public IP address." + }, + "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('name'))]" + }, + "ipAddress": { + "type": "string", + "metadata": { + "description": "The public IP address of the public IP address resource." + }, + "value": "[if(contains(reference('publicIpAddress'), 'ipAddress'), reference('publicIpAddress').ipAddress, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('publicIpAddress', '2023-04-01', 'full').location]" + } + } + } + } + }, + "networkInterface": { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-NetworkInterface', deployment().name)]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[parameters('networkInterfaceName')]" + }, + "ipConfigurations": { + "copy": [ + { + "name": "value", + "count": "[length(parameters('ipConfigurations'))]", + "input": "[createObject('name', if(not(empty(parameters('ipConfigurations')[copyIndex('value')].name)), parameters('ipConfigurations')[copyIndex('value')].name, null()), 'primary', equals(copyIndex('value'), 0), 'privateIPAllocationMethod', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurations')[copyIndex('value')].privateIPAllocationMethod)), parameters('ipConfigurations')[copyIndex('value')].privateIPAllocationMethod, null()), null()), 'privateIPAddress', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'privateIPAddress'), if(not(empty(parameters('ipConfigurations')[copyIndex('value')].privateIPAddress)), parameters('ipConfigurations')[copyIndex('value')].privateIPAddress, null()), null()), 'publicIPAddressResourceId', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'pipconfiguration'), resourceId('Microsoft.Network/publicIPAddresses', format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurations')[copyIndex('value')].pipconfiguration.publicIpNameSuffix)), null()), 'subnetResourceId', parameters('ipConfigurations')[copyIndex('value')].subnetResourceId, 'loadBalancerBackendAddressPools', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'loadBalancerBackendAddressPools'), parameters('ipConfigurations')[copyIndex('value')].loadBalancerBackendAddressPools, null()), 'applicationSecurityGroups', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'applicationSecurityGroups'), parameters('ipConfigurations')[copyIndex('value')].applicationSecurityGroups, null()), 'applicationGatewayBackendAddressPools', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'applicationGatewayBackendAddressPools'), parameters('ipConfigurations')[copyIndex('value')].applicationGatewayBackendAddressPools, null()), 'gatewayLoadBalancer', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'gatewayLoadBalancer'), parameters('ipConfigurations')[copyIndex('value')].gatewayLoadBalancer, null()), 'loadBalancerInboundNatRules', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'loadBalancerInboundNatRules'), parameters('ipConfigurations')[copyIndex('value')].loadBalancerInboundNatRules, null()), 'privateIPAddressVersion', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'privateIPAddressVersion'), parameters('ipConfigurations')[copyIndex('value')].privateIPAddressVersion, null()), 'virtualNetworkTaps', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'virtualNetworkTaps'), parameters('ipConfigurations')[copyIndex('value')].virtualNetworkTaps, null()))]" + } + ] + }, + "location": { + "value": "[parameters('location')]" + }, + "tags": { + "value": "[parameters('tags')]" + }, + "diagnosticSettings": { + "value": "[parameters('diagnosticSettings')]" + }, + "dnsServers": "[if(not(empty(parameters('dnsServers'))), createObject('value', parameters('dnsServers')), createObject('value', createArray()))]", + "enableAcceleratedNetworking": { + "value": "[parameters('enableAcceleratedNetworking')]" + }, + "enableTelemetry": { + "value": "[parameters('enableTelemetry')]" + }, + "enableIPForwarding": { + "value": "[parameters('enableIPForwarding')]" + }, + "lock": { + "value": "[parameters('lock')]" + }, + "networkSecurityGroupResourceId": "[if(not(empty(parameters('networkSecurityGroupResourceId'))), createObject('value', parameters('networkSecurityGroupResourceId')), createObject('value', ''))]", + "roleAssignments": "[if(not(empty(parameters('roleAssignments'))), createObject('value', parameters('roleAssignments')), createObject('value', createArray()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.23.1.45101", + "templateHash": "14617314094453038306" + }, + "name": "Network Interface", + "description": "This module deploys a Network Interface.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "diagnosticSettingType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "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." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + } + }, + "nullable": true + }, + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the network interface." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Resource tags." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "enableIPForwarding": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether IP forwarding is enabled on this network interface." + } + }, + "enableAcceleratedNetworking": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. If the network interface is accelerated networking enabled." + } + }, + "dnsServers": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of DNS servers IP addresses. Use 'AzureProvidedDNS' to switch to azure provided DNS resolution. 'AzureProvidedDNS' value cannot be combined with other IPs, it must be the only value in dnsServers collection." + } + }, + "networkSecurityGroupResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The network security group (NSG) to attach to the network interface." + } + }, + "auxiliaryMode": { + "type": "string", + "defaultValue": "None", + "allowedValues": [ + "Floating", + "MaxConnections", + "None" + ], + "metadata": { + "description": "Optional. Auxiliary mode of Network Interface resource. Not all regions are enabled for Auxiliary Mode Nic." + } + }, + "auxiliarySku": { + "type": "string", + "defaultValue": "None", + "allowedValues": [ + "A1", + "A2", + "A4", + "A8", + "None" + ], + "metadata": { + "description": "Optional. Auxiliary sku of Network Interface resource. Not all regions are enabled for Auxiliary Mode Nic." + } + }, + "disableTcpStateTracking": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether to disable tcp state tracking. Subscription must be registered for the Microsoft.Network/AllowDisableTcpStateTracking feature before this property can be set to true." + } + }, + "ipConfigurations": { + "type": "array", + "metadata": { + "description": "Required. A list of IPConfigurations of the network interface." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "diagnosticSettings": { + "$ref": "#/definitions/diagnosticSettingType", + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + } + }, + "variables": { + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", + "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", + "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2023-07-01", + "name": "[format('46d3xbcp.res.network-networkinterface.{0}.{1}', replace('0.2.2', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "networkInterface": { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2023-04-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "copy": [ + { + "name": "ipConfigurations", + "count": "[length(parameters('ipConfigurations'))]", + "input": { + "name": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'name'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].name, format('ipconfig0{0}', add(copyIndex('ipConfigurations'), 1)))]", + "properties": { + "primary": "[if(equals(copyIndex('ipConfigurations'), 0), true(), false())]", + "privateIPAllocationMethod": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAllocationMethod)), parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAllocationMethod, null()), null())]", + "privateIPAddress": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'privateIPAddress'), if(not(empty(parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAddress)), parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAddress, null()), null())]", + "publicIPAddress": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'publicIPAddressResourceId'), if(not(equals(parameters('ipConfigurations')[copyIndex('ipConfigurations')].publicIPAddressResourceId, null())), createObject('id', parameters('ipConfigurations')[copyIndex('ipConfigurations')].publicIPAddressResourceId), null()), null())]", + "subnet": { + "id": "[parameters('ipConfigurations')[copyIndex('ipConfigurations')].subnetResourceId]" + }, + "loadBalancerBackendAddressPools": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'loadBalancerBackendAddressPools'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].loadBalancerBackendAddressPools, null())]", + "applicationSecurityGroups": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'applicationSecurityGroups'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].applicationSecurityGroups, null())]", + "applicationGatewayBackendAddressPools": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'applicationGatewayBackendAddressPools'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].applicationGatewayBackendAddressPools, null())]", + "gatewayLoadBalancer": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'gatewayLoadBalancer'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].gatewayLoadBalancer, null())]", + "loadBalancerInboundNatRules": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'loadBalancerInboundNatRules'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].loadBalancerInboundNatRules, null())]", + "privateIPAddressVersion": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'privateIPAddressVersion'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAddressVersion, null())]", + "virtualNetworkTaps": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'virtualNetworkTaps'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].virtualNetworkTaps, null())]" + } + } + } + ], + "auxiliaryMode": "[parameters('auxiliaryMode')]", + "auxiliarySku": "[parameters('auxiliarySku')]", + "disableTcpStateTracking": "[parameters('disableTcpStateTracking')]", + "dnsSettings": "[if(not(empty(parameters('dnsServers'))), createObject('dnsServers', parameters('dnsServers')), null())]", + "enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]", + "enableIPForwarding": "[parameters('enableIPForwarding')]", + "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupResourceId'))), createObject('id', parameters('networkSecurityGroupResourceId')), null())]" + } + }, + "networkInterface_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "networkInterface" + ] + }, + "networkInterface_diagnosticSettings": { + "copy": { + "name": "networkInterface_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "networkInterface" + ] + }, + "networkInterface_roleAssignments": { + "copy": { + "name": "networkInterface_roleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('name'))]", + "name": "[guid(resourceId('Microsoft.Network/networkInterfaces', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "properties": { + "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", + "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "networkInterface" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed resource." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed resource." + }, + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed resource." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('networkInterface', '2023-04-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "networkInterface_publicIPAddresses" + ] + } + } + } + } + }, + "vm_aadJoinExtension": { + "condition": "[parameters('extensionAadJoinConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-AADLogin', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "AADLogin" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Azure.ActiveDirectory" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AADLoginForWindows'), createObject('value', 'AADSSHLoginforLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionAadJoinConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAadJoinConfig').typeHandlerVersion), createObject('value', '1.0'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAadJoinConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAadJoinConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionAadJoinConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAadJoinConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": "[if(contains(parameters('extensionAadJoinConfig'), 'settings'), createObject('value', parameters('extensionAadJoinConfig').settings), createObject('value', createObject()))]", + "tags": { + "value": "[coalesce(tryGet(parameters('extensionAadJoinConfig'), 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_domainJoinExtension": { + "condition": "[parameters('extensionDomainJoinConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DomainJoin" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Compute" + }, + "type": { + "value": "JsonADDomainExtension" + }, + "typeHandlerVersion": "[if(contains(parameters('extensionDomainJoinConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDomainJoinConfig').typeHandlerVersion), createObject('value', '1.3'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDomainJoinConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDomainJoinConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionDomainJoinConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDomainJoinConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": "[parameters('extensionDomainJoinConfig').settings]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('extensionDomainJoinConfig'), 'tags'), parameters('tags'))]" + }, + "protectedSettings": { + "value": { + "Password": "[parameters('extensionDomainJoinPassword')]" + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_microsoftAntiMalwareExtension": { + "condition": "[parameters('extensionAntiMalwareConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "MicrosoftAntiMalware" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": { + "value": "IaaSAntimalware" + }, + "typeHandlerVersion": "[if(contains(parameters('extensionAntiMalwareConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAntiMalwareConfig').typeHandlerVersion), createObject('value', '1.3'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAntiMalwareConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAntiMalwareConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionAntiMalwareConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAntiMalwareConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": "[parameters('extensionAntiMalwareConfig').settings]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('extensionAntiMalwareConfig'), 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_azureMonitoringAgentExtension": { + "condition": "[parameters('extensionMonitoringAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-AzureMonitoringAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "AzureMonitoringAgent" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Azure.Monitor" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AzureMonitorWindowsAgent'), createObject('value', 'AzureMonitorLinuxAgent'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionMonitoringAgentConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '1.0'), createObject('value', '1.21')))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionMonitoringAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionMonitoringAgentConfig').enableAutomaticUpgrade), createObject('value', true()))]", + "tags": { + "value": "[coalesce(tryGet(parameters('extensionMonitoringAgentConfig'), 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_dependencyAgentExtension": { + "condition": "[parameters('extensionDependencyAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DependencyAgent" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Azure.Monitoring.DependencyAgent" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'DependencyAgentWindows'), createObject('value', 'DependencyAgentLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionDependencyAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDependencyAgentConfig').typeHandlerVersion), createObject('value', '9.5'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDependencyAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDependencyAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionDependencyAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDependencyAgentConfig').enableAutomaticUpgrade), createObject('value', true()))]", + "tags": { + "value": "[coalesce(tryGet(parameters('extensionDependencyAgentConfig'), 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_networkWatcherAgentExtension": { + "condition": "[parameters('extensionNetworkWatcherAgentConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "NetworkWatcherAgent" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Azure.NetworkWatcher" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'NetworkWatcherAgentWindows'), createObject('value', 'NetworkWatcherAgentLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').typeHandlerVersion), createObject('value', '1.4'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "tags": { + "value": "[coalesce(tryGet(parameters('extensionNetworkWatcherAgentConfig'), 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_desiredStateConfigurationExtension": { + "condition": "[parameters('extensionDSCConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "DesiredStateConfiguration" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Powershell" + }, + "type": { + "value": "DSC" + }, + "typeHandlerVersion": "[if(contains(parameters('extensionDSCConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDSCConfig').typeHandlerVersion), createObject('value', '2.77'))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDSCConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDSCConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionDSCConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDSCConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": "[if(contains(parameters('extensionDSCConfig'), 'settings'), createObject('value', parameters('extensionDSCConfig').settings), createObject('value', createObject()))]", + "tags": { + "value": "[coalesce(tryGet(parameters('extensionDSCConfig'), 'tags'), parameters('tags'))]" + }, + "protectedSettings": "[if(contains(parameters('extensionDSCConfig'), 'protectedSettings'), createObject('value', parameters('extensionDSCConfig').protectedSettings), createObject('value', createObject()))]" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm" + ] + }, + "vm_customScriptExtension": { + "condition": "[parameters('extensionCustomScriptConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "CustomScriptExtension" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'Microsoft.Compute'), createObject('value', 'Microsoft.Azure.Extensions'))]", + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'CustomScriptExtension'), createObject('value', 'CustomScript'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionCustomScriptConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionCustomScriptConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '1.10'), createObject('value', '2.1')))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionCustomScriptConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionCustomScriptConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionCustomScriptConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionCustomScriptConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "settings": { + "value": { + "copy": [ + { + "name": "fileUris", + "count": "[length(parameters('extensionCustomScriptConfig').fileData)]", + "input": "[if(contains(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')], 'storageAccountId'), format('{0}?{1}', parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri, listAccountSas(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].storageAccountId, '2019-04-01', variables('accountSasProperties')).accountSasToken), parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri)]" + } + ] + } + }, + "tags": { + "value": "[coalesce(tryGet(parameters('extensionCustomScriptConfig'), 'tags'), parameters('tags'))]" + }, + "protectedSettings": { + "value": "[parameters('extensionCustomScriptProtectedSetting')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm", + "vm_desiredStateConfigurationExtension" + ] + }, + "vm_azureDiskEncryptionExtension": { + "condition": "[parameters('extensionAzureDiskEncryptionConfig').enabled]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-AzureDiskEncryption', uniqueString(deployment().name, parameters('location')))]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "virtualMachineName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "AzureDiskEncryption" + }, + "location": { + "value": "[parameters('location')]" + }, + "publisher": { + "value": "Microsoft.Azure.Security" + }, + "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AzureDiskEncryption'), createObject('value', 'AzureDiskEncryptionForLinux'))]", + "typeHandlerVersion": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '2.2'), createObject('value', '1.1')))]", + "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').autoUpgradeMinorVersion), createObject('value', true()))]", + "enableAutomaticUpgrade": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').enableAutomaticUpgrade), createObject('value', false()))]", + "forceUpdateTag": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'forceUpdateTag'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').forceUpdateTag), createObject('value', '1.0'))]", + "settings": { + "value": "[parameters('extensionAzureDiskEncryptionConfig').settings]" + }, + "tags": { + "value": "[coalesce(tryGet(parameters('extensionAzureDiskEncryptionConfig'), 'tags'), parameters('tags'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "13562327621635125722" + }, + "name": "Virtual Machine Extensions", + "description": "This module deploys a Virtual Machine Extension.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "virtualMachineName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the virtual machine extension." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. The location the extension is deployed to." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the extension handler publisher." + } + }, + "type": { + "type": "string", + "metadata": { + "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." + } + }, + "typeHandlerVersion": { + "type": "string", + "metadata": { + "description": "Required. Specifies the version of the script handler." + } + }, + "autoUpgradeMinorVersion": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." + } + }, + "forceUpdateTag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." + } + }, + "settings": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific settings." + } + }, + "protectedSettings": { + "type": "secureObject", + "nullable": true, + "metadata": { + "description": "Optional. Any object that contains the extension specific protected settings." + } + }, + "supressFailures": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." + } + }, + "enableAutomaticUpgrade": { + "type": "bool", + "metadata": { + "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + } + }, + "resources": { + "virtualMachine": { + "existing": true, + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2022-11-01", + "name": "[parameters('virtualMachineName')]" + }, + "extension": { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2022-11-01", + "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "publisher": "[parameters('publisher')]", + "type": "[parameters('type')]", + "typeHandlerVersion": "[parameters('typeHandlerVersion')]", + "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", + "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", + "forceUpdateTag": "[parameters('forceUpdateTag')]", + "settings": "[parameters('settings')]", + "protectedSettings": "[parameters('protectedSettings')]", + "suppressFailures": "[parameters('supressFailures')]" + }, + "dependsOn": [ + "virtualMachine" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the extension." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the extension." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the extension was created in." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('extension', '2022-11-01', 'full').location]" + } + } + } + }, + "dependsOn": [ + "vm", + "vm_azureMonitoringAgentExtension", + "vm_customScriptExtension" + ] + }, + "vm_backup": { + "condition": "[not(empty(parameters('backupVaultName')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-VM-Backup', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[parameters('backupVaultResourceGroup')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[format('vm;iaasvmcontainerv2;{0};{1}', resourceGroup().name, parameters('name'))]" + }, + "location": { + "value": "[parameters('location')]" + }, + "policyId": { + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('backupVaultName'), parameters('backupPolicyName'))]" + }, + "protectedItemType": { + "value": "Microsoft.Compute/virtualMachines" + }, + "protectionContainerName": { + "value": "[format('iaasvmcontainer;iaasvmcontainerv2;{0};{1}', resourceGroup().name, parameters('name'))]" + }, + "recoveryVaultName": { + "value": "[parameters('backupVaultName')]" + }, + "sourceResourceId": { + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.24.24.22086", + "templateHash": "12595215410082531283" + }, + "name": "Recovery Service Vaults Protection Container Protected Item", + "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", + "owner": "Azure/module-maintainers" + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the resource." + } + }, + "protectionContainerName": { + "type": "string", + "metadata": { + "description": "Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment." + } + }, + "recoveryVaultName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "protectedItemType": { + "type": "string", + "allowedValues": [ + "AzureFileShareProtectedItem", + "AzureVmWorkloadSAPAseDatabase", + "AzureVmWorkloadSAPHanaDatabase", + "AzureVmWorkloadSQLDatabase", + "DPMProtectedItem", + "GenericProtectedItem", + "MabFileFolderProtectedItem", + "Microsoft.ClassicCompute/virtualMachines", + "Microsoft.Compute/virtualMachines", + "Microsoft.Sql/servers/databases" + ], + "metadata": { + "description": "Required. The backup item type." + } + }, + "policyId": { + "type": "string", + "metadata": { + "description": "Required. ID of the backup policy with which this item is backed up." + } + }, + "sourceResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the resource to back up." + } + } + }, + "resources": [ + { + "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", + "apiVersion": "2023-01-01", + "name": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]", + "location": "[parameters('location')]", + "properties": { + "protectedItemType": "[parameters('protectedItemType')]", + "policyId": "[parameters('policyId')]", + "sourceResourceId": "[parameters('sourceResourceId')]" + } + } + ], + "outputs": { + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the Resource Group the protected item was created in." + }, + "value": "[resourceGroup().name]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the protected item." + }, + "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems', split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[2], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[3])]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The Name of the protected item." + }, + "value": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]" + } + } + } + }, + "dependsOn": [ + "vm", + "vm_aadJoinExtension", + "vm_azureMonitoringAgentExtension", + "vm_customScriptExtension", + "vm_dependencyAgentExtension", + "vm_desiredStateConfigurationExtension", + "vm_domainJoinExtension", + "vm_microsoftAntiMalwareExtension", + "vm_networkWatcherAgentExtension" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the VM." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the VM." + }, + "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the VM was created in." + }, + "value": "[resourceGroup().name]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('vm', '2022-11-01', 'full').identity, 'principalId')), reference('vm', '2022-11-01', 'full').identity.principalId, '')]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('vm', '2022-11-01', 'full').location]" + } + } +} \ No newline at end of file diff --git a/avm/res/compute/virtual-machine/modules/nic-configuration.bicep b/avm/res/compute/virtual-machine/modules/nic-configuration.bicep new file mode 100644 index 0000000000..770d924a7d --- /dev/null +++ b/avm/res/compute/virtual-machine/modules/nic-configuration.bicep @@ -0,0 +1,153 @@ +param networkInterfaceName string +param virtualMachineName string +param location string +param tags object? +param enableIPForwarding bool = false +param enableAcceleratedNetworking bool = false +param dnsServers array = [] + +@description('Required. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableTelemetry bool + +@description('Optional. The network security group (NSG) to attach to the network interface.') +param networkSecurityGroupResourceId string = '' + +param ipConfigurations array +param lock lockType + +@description('Optional. The diagnostic settings of the Network Interface.') +param diagnosticSettings diagnosticSettingType + +@description('Optional. Array of role assignments to create.') +param roleAssignments roleAssignmentType + +module networkInterface_publicIPAddresses 'br/public:avm/res/network/public-ip-address:0.2.1' = [for (ipConfiguration, index) in ipConfigurations: if (contains(ipConfiguration, 'pipconfiguration')) { + name: '${deployment().name}-publicIP-${index}' + params: { + name: '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}' + diagnosticSettings: ipConfiguration.?diagnosticSettings + location: location + lock: lock + publicIPAddressVersion: contains(ipConfiguration, 'publicIPAddressVersion') ? ipConfiguration.publicIPAddressVersion : 'IPv4' + publicIPAllocationMethod: contains(ipConfiguration, 'publicIPAllocationMethod') ? ipConfiguration.publicIPAllocationMethod : 'Static' + publicIpPrefixResourceId: contains(ipConfiguration, 'publicIPPrefixResourceId') ? ipConfiguration.publicIPPrefixResourceId : '' + roleAssignments: contains(ipConfiguration, 'roleAssignments') ? ipConfiguration.roleAssignments : [] + skuName: contains(ipConfiguration, 'skuName') ? ipConfiguration.skuName : 'Standard' + skuTier: contains(ipConfiguration, 'skuTier') ? ipConfiguration.skuTier : 'Regional' + tags: ipConfiguration.?tags ?? tags + zones: contains(ipConfiguration, 'zones') ? ipConfiguration.zones : [ + '1' + '2' + '3' + ] + enableTelemetry: enableTelemetry + } +}] + +module networkInterface 'br/public:avm/res/network/network-interface:0.2.2' = { + name: '${deployment().name}-NetworkInterface' + params: { + name: networkInterfaceName + ipConfigurations: [for (ipConfiguration, index) in ipConfigurations: { + name: !empty(ipConfiguration.name) ? ipConfiguration.name : null + primary: index == 0 + privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) : null + privateIPAddress: contains(ipConfiguration, 'privateIPAddress') ? (!empty(ipConfiguration.privateIPAddress) ? ipConfiguration.privateIPAddress : null) : null + publicIPAddressResourceId: contains(ipConfiguration, 'pipconfiguration') ? resourceId('Microsoft.Network/publicIPAddresses', '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}') : null + subnetResourceId: ipConfiguration.subnetResourceId + loadBalancerBackendAddressPools: contains(ipConfiguration, 'loadBalancerBackendAddressPools') ? ipConfiguration.loadBalancerBackendAddressPools : null + applicationSecurityGroups: contains(ipConfiguration, 'applicationSecurityGroups') ? ipConfiguration.applicationSecurityGroups : null + applicationGatewayBackendAddressPools: contains(ipConfiguration, 'applicationGatewayBackendAddressPools') ? ipConfiguration.applicationGatewayBackendAddressPools : null + gatewayLoadBalancer: contains(ipConfiguration, 'gatewayLoadBalancer') ? ipConfiguration.gatewayLoadBalancer : null + loadBalancerInboundNatRules: contains(ipConfiguration, 'loadBalancerInboundNatRules') ? ipConfiguration.loadBalancerInboundNatRules : null + privateIPAddressVersion: contains(ipConfiguration, 'privateIPAddressVersion') ? ipConfiguration.privateIPAddressVersion : null + virtualNetworkTaps: contains(ipConfiguration, 'virtualNetworkTaps') ? ipConfiguration.virtualNetworkTaps : null + }] + location: location + tags: tags + diagnosticSettings: diagnosticSettings + dnsServers: !empty(dnsServers) ? dnsServers : [] + enableAcceleratedNetworking: enableAcceleratedNetworking + enableTelemetry: enableTelemetry + enableIPForwarding: enableIPForwarding + lock: lock + networkSecurityGroupResourceId: !empty(networkSecurityGroupResourceId) ? networkSecurityGroupResourceId : '' + roleAssignments: !empty(roleAssignments) ? roleAssignments : [] + } + dependsOn: [ + networkInterface_publicIPAddresses + ] +} + +// =============== // +// Definitions // +// =============== // + +type lockType = { + @description('Optional. Specify the name of lock.') + name: string? + + @description('Optional. Specify the type of lock.') + kind: ('CanNotDelete' | 'ReadOnly' | 'None')? +}? + +type diagnosticSettingType = { + @description('Optional. The name of diagnostic setting.') + name: string? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + logCategoriesAndGroups: { + @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') + category: string? + + @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to llLogs to collect all logs.') + categoryGroup: string? + }[]? + + @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') + metricCategories: { + @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to AllMetrics to collect all metrics.') + category: string + }[]? + + @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') + logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? + + @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + workspaceResourceId: string? + + @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + storageAccountResourceId: 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.') + eventHubAuthorizationRuleResourceId: 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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') + eventHubName: string? + + @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') + marketplacePartnerResourceId: string? +}[]? + +type roleAssignmentType = { + @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') + roleDefinitionIdOrName: string + + @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') + principalId: string + + @description('Optional. The principal type of the assigned principal ID.') + principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? + + @description('Optional. The description of the role assignment.') + description: string? + + @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') + condition: string? + + @description('Optional. Version of the condition.') + conditionVersion: '2.0'? + + @description('Optional. The Resource Id of the delegated managed identity resource.') + delegatedManagedIdentityResourceId: string? +}[]? diff --git a/avm/res/compute/virtual-machine/modules/protected-item.bicep b/avm/res/compute/virtual-machine/modules/protected-item.bicep new file mode 100644 index 0000000000..dbba0616ac --- /dev/null +++ b/avm/res/compute/virtual-machine/modules/protected-item.bicep @@ -0,0 +1,55 @@ +metadata name = 'Recovery Service Vaults Protection Container Protected Item' +metadata description = 'This module deploys a Recovery Services Vault Protection Container Protected Item.' +metadata owner = 'Azure/module-maintainers' + +@description('Required. Name of the resource.') +param name string + +@description('Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment.') +param protectionContainerName string + +@description('Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment.') +param recoveryVaultName string + +@description('Optional. Location for all resources.') +param location string = resourceGroup().location + +@allowed([ + 'AzureFileShareProtectedItem' + 'AzureVmWorkloadSAPAseDatabase' + 'AzureVmWorkloadSAPHanaDatabase' + 'AzureVmWorkloadSQLDatabase' + 'DPMProtectedItem' + 'GenericProtectedItem' + 'MabFileFolderProtectedItem' + 'Microsoft.ClassicCompute/virtualMachines' + 'Microsoft.Compute/virtualMachines' + 'Microsoft.Sql/servers/databases' +]) +@description('Required. The backup item type.') +param protectedItemType string + +@description('Required. ID of the backup policy with which this item is backed up.') +param policyId string + +@description('Required. Resource ID of the resource to back up.') +param sourceResourceId string + +resource protectedItem 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2023-01-01' = { + name: '${recoveryVaultName}/Azure/${protectionContainerName}/${name}' + location: location + properties: { + protectedItemType: any(protectedItemType) + policyId: policyId + sourceResourceId: sourceResourceId + } +} + +@description('The name of the Resource Group the protected item was created in.') +output resourceGroupName string = resourceGroup().name + +@description('The resource ID of the protected item.') +output resourceId string = protectedItem.id + +@description('The Name of the protected item.') +output name string = protectedItem.name diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep new file mode 100644 index 0000000000..fe37b069fa --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep @@ -0,0 +1,86 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Deployment Script to create for the SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: ' -SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The Public Key of the created SSH Key.') +output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep new file mode 100644 index 0000000000..b506288b88 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep @@ -0,0 +1,123 @@ +targetScope = 'subscription' + +metadata name = 'Using automanage for the VM.' +metadata description = 'This instance deploys the module with registering to an automation account.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmlinatmg' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { +// name: sshKeyName +// scope: resourceGroup +// } + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: location + name: '${namePrefix}${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + zones: [ + '1' + '2' + '3' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_DS2_v2' + configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + disablePasswordAuthentication: true + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + dependsOn: [ + nestedDependencies // Required to leverage `existing` SSH key reference + ] +}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep new file mode 100644 index 0000000000..023a59cca3 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep @@ -0,0 +1,86 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Deployment Script to create for the SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The Public Key of the created SSH Key.') +output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep new file mode 100644 index 0000000000..ff60259195 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep @@ -0,0 +1,103 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmlinmin' + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' + sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { +// name: sshKeyName +// scope: resourceGroup +// } + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: location + name: '${namePrefix}${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'Canonical' + offer: '0001-com-ubuntu-server-jammy' + sku: '22_04-lts-gen2' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + caching: 'ReadWrite' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_DS2_v2' + disablePasswordAuthentication: true + publicKeys: [ + { + keyData: nestedDependencies.outputs.SSHKeyPublicKey + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + } + dependsOn: [ + nestedDependencies // Required to leverage `existing` SSH key reference + ] +}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep new file mode 100644 index 0000000000..4d6d69ed7a --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep @@ -0,0 +1,267 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Application Security Group to create.') +param applicationSecurityGroupName string + +@description('Required. The name of the Load Balancer to create.') +param loadBalancerName string + +@description('Required. The name of the Recovery Services Vault to create.') +param recoveryServicesVaultName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName string + +@description('Required. The name of the Proximity Placement Group to create.') +param proximityPlacementGroupName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-04-01' = { + name: applicationSecurityGroupName + location: location +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { + name: loadBalancerName + location: location + sku: { + name: 'Standard' + } + properties: { + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + properties: { + subnet: virtualNetwork.properties.subnets[0] + } + } + ] + backendAddressPools: [ + { + name: 'servers' + } + ] + } +} + +resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-04-01' = { + name: recoveryServicesVaultName + location: location + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: {} + + resource backupPolicy 'backupPolicies@2022-03-01' = { + name: 'backupPolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + retentionPolicy: { + retentionPolicyType: 'LongTermRetentionPolicy' + dailySchedule: { + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 180 + durationType: 'Days' + } + } + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + } + monthlySchedule: { + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 60 + durationType: 'Months' + } + } + yearlySchedule: { + retentionScheduleFormatType: 'Weekly' + monthsOfYear: [ + 'January' + ] + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + } + } + instantRpRetentionRangeInDays: 2 + timeZone: 'UTC' + protectedItemsCount: 0 + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: 'scripts' + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') + } +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { + name: proximityPlacementGroupName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Application Security Group.') +output applicationSecurityGroupResourceId string = applicationSecurityGroup.id + +@description('The resource ID of the created Load Balancer Backend Pool.') +output loadBalancerBackendPoolResourceId string = loadBalancer.properties.backendAddressPools[0].id + +@description('The name of the created Recovery Services Vault.') +output recoveryServicesVaultName string = recoveryServicesVault.name + +@description('The name of the Resource Group, the Recovery Services Vault was created in.') +output recoveryServicesVaultResourceGroupName string = resourceGroup().name + +@description('The name of the Backup Policy created in the Backup Recovery Vault.') +output recoveryServicesVaultBackupPolicyName string = recoveryServicesVault::backupPolicy.name + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The name of the Custom Script Extension in the created Storage Account.') +output storageAccountCSEFileName string = storageAccountCSEFileName + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' + +@description('The resource ID of the created Proximity Placement Group.') +output proximityPlacementGroupResourceId string = proximityPlacementGroup.id diff --git a/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep new file mode 100644 index 0000000000..21c55ad87c --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep @@ -0,0 +1,293 @@ +targetScope = 'subscription' + +metadata name = 'WAF-aligned' +metadata description = 'This instance deploys the module in alignment with the best-practices of the Well-Architected Framework.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmwinwaf' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + applicationSecurityGroupName: 'dep-${namePrefix}-asg-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' + recoveryServicesVaultName: 'dep-${namePrefix}-rsv-${serviceShort}' + storageAccountName: 'dep${namePrefix}sa${serviceShort}01' + storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' + proximityPlacementGroupName: 'dep-${namePrefix}-ppg-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: location + name: '${namePrefix}${serviceShort}' + computerName: '${namePrefix}winvm1' + adminUsername: 'VMAdmin' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2019-datacenter' + version: 'latest' + } + nicConfigurations: [ + { + deleteOption: 'Delete' + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + loadBalancerBackendAddressPools: [ + { + id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId + } + ] + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + zones: [ + '1' + '2' + '3' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + ] + nicSuffix: '-nic-01' + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + ] + osDisk: { + caching: 'ReadWrite' + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + adminPassword: password + availabilityZone: 2 + backupPolicyName: nestedDependencies.outputs.recoveryServicesVaultBackupPolicyName + backupVaultName: nestedDependencies.outputs.recoveryServicesVaultName + backupVaultResourceGroup: nestedDependencies.outputs.recoveryServicesVaultResourceGroupName + dataDisks: [ + { + caching: 'ReadOnly' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'ReadOnly' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + enableAutomaticUpdates: true + patchMode: 'AutomaticByPlatform' + encryptionAtHost: false + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: 'true' + Exclusions: { + Extensions: '.ext1;.ext2' + Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' + Processes: 'excludedproc1.exe;excludedproc2.exe' + } + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionCustomScriptProtectedSetting: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' + } + extensionDependencyAgentConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + } + extensionAadJoinConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionDSCConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionMonitoringAgentConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionNetworkWatcherAgentConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep new file mode 100644 index 0000000000..68972ec7ec --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep @@ -0,0 +1,30 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep new file mode 100644 index 0000000000..4c9c55e6b3 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep @@ -0,0 +1,86 @@ +targetScope = 'subscription' + +metadata name = 'Using only defaults' +metadata description = 'This instance deploys the module with the minimum set of required parameters.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmwinmin' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: location + name: '${namePrefix}${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + caching: 'ReadWrite' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + adminPassword: password + } +}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep new file mode 100644 index 0000000000..e198bcd227 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep @@ -0,0 +1,310 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Application Security Group to create.') +param applicationSecurityGroupName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Load Balancer to create.') +param loadBalancerName string + +@description('Required. The name of the Recovery Services Vault to create.') +param recoveryServicesVaultName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName string + +@description('Required. The name of the Proximity Placement Group to create.') +param proximityPlacementGroupName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-04-01' = { + name: applicationSecurityGroupName + location: location +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { + name: loadBalancerName + location: location + sku: { + name: 'Standard' + } + properties: { + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + properties: { + subnet: virtualNetwork.properties.subnets[0] + } + } + ] + backendAddressPools: [ + { + name: 'servers' + } + ] + } +} + +resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-04-01' = { + name: recoveryServicesVaultName + location: location + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: {} + + resource backupPolicy 'backupPolicies@2022-03-01' = { + name: 'backupPolicy' + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + retentionPolicy: { + retentionPolicyType: 'LongTermRetentionPolicy' + dailySchedule: { + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 180 + durationType: 'Days' + } + } + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + } + monthlySchedule: { + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 60 + durationType: 'Months' + } + } + yearlySchedule: { + retentionScheduleFormatType: 'Weekly' + monthsOfYear: [ + 'January' + ] + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + } + } + instantRpRetentionRangeInDays: 2 + timeZone: 'UTC' + protectedItemsCount: 0 + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource msiKVReadRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-KeyVault-Key-Read-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: 'scripts' + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '9.0' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { + name: proximityPlacementGroupName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Application Security Group.') +output applicationSecurityGroupResourceId string = applicationSecurityGroup.id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Load Balancer Backend Pool.') +output loadBalancerBackendPoolResourceId string = loadBalancer.properties.backendAddressPools[0].id + +@description('The name of the created Recovery Services Vault.') +output recoveryServicesVaultName string = recoveryServicesVault.name + +@description('The name of the Resource Group, the Recovery Services Vault was created in.') +output recoveryServicesVaultResourceGroupName string = resourceGroup().name + +@description('The name of the Backup Policy created in the Backup Recovery Vault.') +output recoveryServicesVaultBackupPolicyName string = recoveryServicesVault::backupPolicy.name + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The name of the Custom Script Extension in the created Storage Account.') +output storageAccountCSEFileName string = storageAccountCSEFileName + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' + +@description('The resource ID of the created Proximity Placement Group.') +output proximityPlacementGroupResourceId string = proximityPlacementGroup.id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep new file mode 100644 index 0000000000..51e19418b8 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep @@ -0,0 +1,331 @@ +targetScope = 'subscription' + +metadata name = 'Using large parameter set' +metadata description = 'This instance deploys the module with most of its features enabled.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmwinmax' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + applicationSecurityGroupName: 'dep-${namePrefix}-asg-${serviceShort}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' + loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' + recoveryServicesVaultName: 'dep-${namePrefix}-rsv-${serviceShort}' + storageAccountName: 'dep${namePrefix}sa${serviceShort}01' + storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' + proximityPlacementGroupName: 'dep-${namePrefix}-ppg-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' + eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: location + name: '${namePrefix}${serviceShort}' + computerName: '${namePrefix}winvm1' + adminUsername: 'VMAdmin' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2019-datacenter' + version: 'latest' + } + nicConfigurations: [ + { + deleteOption: 'Delete' + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: nestedDependencies.outputs.applicationSecurityGroupResourceId + } + ] + loadBalancerBackendAddressPools: [ + { + id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId + } + ] + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + } + zones: [ + '1' + '2' + '3' + ] + subnetResourceId: nestedDependencies.outputs.subnetResourceId + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + ] + nicSuffix: '-nic-01' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + diagnosticSettings: [ + { + name: 'customSetting' + metricCategories: [ + { + category: 'AllMetrics' + } + ] + eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId + workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + } + ] + } + ] + osDisk: { + caching: 'ReadWrite' + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + adminPassword: password + availabilityZone: 2 + backupPolicyName: nestedDependencies.outputs.recoveryServicesVaultBackupPolicyName + backupVaultName: nestedDependencies.outputs.recoveryServicesVaultName + backupVaultResourceGroup: nestedDependencies.outputs.recoveryServicesVaultResourceGroupName + dataDisks: [ + { + caching: 'None' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'None' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + enableAutomaticUpdates: true + patchMode: 'AutomaticByPlatform' + encryptionAtHost: false + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: 'true' + Exclusions: { + Extensions: '.ext1;.ext2' + Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' + Processes: 'excludedproc1.exe;excludedproc2.exe' + } + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: nestedDependencies.outputs.storageAccountResourceId + uri: nestedDependencies.outputs.storageAccountCSEFileUrl + } + ] + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionCustomScriptProtectedSetting: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' + } + extensionDependencyAgentConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionAzureDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + KeyVaultURL: nestedDependencies.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + } + extensionAadJoinConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionDSCConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionMonitoringAgentConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + extensionNetworkWatcherAgentConfig: { + enabled: true + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } + lock: { + kind: 'CanNotDelete' + name: 'myCustomLockName' + } + proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId + roleAssignments: [ + { + roleDefinitionIdOrName: 'Owner' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + { + roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') + principalId: nestedDependencies.outputs.managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } + ] + managedIdentities: { + systemAssigned: true + userAssignedResourceIds: [ + nestedDependencies.outputs.managedIdentityResourceId + ] + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + } +}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep new file mode 100644 index 0000000000..e5cb91cea0 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep @@ -0,0 +1,92 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Disk Encryption Set to create.') +param diskEncryptionSetName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +var addressPrefix = '10.0.0.0/16' + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + addressPrefix + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: cidrSubnet(addressPrefix, 16, 0) + } + } + ] + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true // Required by disk encryption set + softDeleteRetentionInDays: 7 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { + name: diskEncryptionSetName + location: location + identity: { + type: 'SystemAssigned' + } + properties: { + activeKey: { + sourceVault: { + id: keyVault.id + } + keyUrl: keyVault::key.properties.keyUriWithVersion + } + encryptionType: 'EncryptionAtRestWithPlatformAndCustomerKeys' + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(keyVault::key.id, 'Key Vault Crypto User', diskEncryptionSet.id) + scope: keyVault + properties: { + principalId: diskEncryptionSet.identity.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User + principalType: 'ServicePrincipal' + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Disk Encryption Set.') +output diskEncryptionSetResourceId string = diskEncryptionSet.id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep new file mode 100644 index 0000000000..66b285f155 --- /dev/null +++ b/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep @@ -0,0 +1,105 @@ +targetScope = 'subscription' + +metadata name = 'Using disk encryption set for the VM.' +metadata description = 'This instance deploys the module with disk enryption set.' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'cvmwincmk' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '#_namePrefix_#' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep${namePrefix}kv${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // +@batchSize(1) +module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' + params: { + location: location + name: '${namePrefix}${serviceShort}' + adminUsername: 'VMAdministrator' + imageReference: { + publisher: 'MicrosoftWindowsServer' + offer: 'WindowsServer' + sku: '2019-datacenter' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: nestedDependencies.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + diskEncryptionSet: { + id: nestedDependencies.outputs.diskEncryptionSetResourceId + } + } + } + osType: 'Windows' + vmSize: 'Standard_DS2_v2' + adminPassword: password + dataDisks: [ + { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + diskEncryptionSet: { + id: nestedDependencies.outputs.diskEncryptionSetResourceId + } + } + } + ] + } +}] diff --git a/avm/res/compute/virtual-machine/version.json b/avm/res/compute/virtual-machine/version.json new file mode 100644 index 0000000000..8def869ede --- /dev/null +++ b/avm/res/compute/virtual-machine/version.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", + "version": "0.1", + "pathFilters": [ + "./main.json" + ] +} From 22ac0f3b9e8095d8e9565bcee9ddc92e9cc7d461 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Thu, 4 Jan 2024 17:38:22 +0100 Subject: [PATCH 30/35] Fixed reference resolution --- avm/res/compute/virtual-machine/README.md | 7 ++++++- .../sharedScripts/helper/Get-CrossReferencedModuleList.ps1 | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md index deeb7b539f..ab7f9d8f9a 100644 --- a/avm/res/compute/virtual-machine/README.md +++ b/avm/res/compute/virtual-machine/README.md @@ -2574,4 +2574,9 @@ Do not provide a value! This date value is used to generate a registration token ## Cross-referenced modules -_None_ +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/res/network/network-interface:0.2.2` | Remote reference | +| `br/public:avm/res/network/public-ip-address:0.2.1` | Remote reference | diff --git a/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 b/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 index 8a6d00844a..4b85908719 100644 --- a/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 +++ b/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 @@ -152,7 +152,9 @@ function Get-CrossReferencedModuleList { $resultSet = [ordered]@{} # Collect data - $moduleTemplatePaths = (Get-ChildItem -Path $path -Recurse -File -Filter 'main.bicep').FullName + $moduleTemplatePaths = (Get-ChildItem -Path $path -Recurse -File -Filter '*.bicep').FullName | Where-Object { + $_ -notmatch '.*[\\|\/]tools[\\|\/].*' + } | Sort-Object $templateMap = @{} foreach ($moduleTemplatePath in $moduleTemplatePaths) { $templateMap[$moduleTemplatePath] = Get-Content -Path $moduleTemplatePath From e6337259f4a109f776c99286f6fafcdadd471b18 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Thu, 4 Jan 2024 17:55:59 +0100 Subject: [PATCH 31/35] Update to latest --- .../sharedScripts/helper/Get-CrossReferencedModuleList.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 b/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 index 4b85908719..713e2268c5 100644 --- a/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 +++ b/avm/utilities/pipelines/sharedScripts/helper/Get-CrossReferencedModuleList.ps1 @@ -153,7 +153,8 @@ function Get-CrossReferencedModuleList { # Collect data $moduleTemplatePaths = (Get-ChildItem -Path $path -Recurse -File -Filter '*.bicep').FullName | Where-Object { - $_ -notmatch '.*[\\|\/]tools[\\|\/].*' + # No files inthe [/utilities/tools/] folder and none in the [/tests/] folder + $_ -notmatch '.*[\\|\/]tools[\\|\/].*|.*[\\|\/]tests[\\|\/].*' } | Sort-Object $templateMap = @{} foreach ($moduleTemplatePath in $moduleTemplatePaths) { From ede10f9757fe2f9392da5d5e3bcc7ab2f782b108 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Thu, 4 Jan 2024 17:57:17 +0100 Subject: [PATCH 32/35] Update to latest --- .../avm.res.storage.storage-account.yml | 83 - ....virtual-machine-images.image-template.yml | 83 - .../virtual-machine/extension/README.md | 156 - .../virtual-machine/extension/main.bicep | 77 - .../virtual-machine/extension/main.json | 160 - avm/res/compute/virtual-machine/main.bicep | 769 --- avm/res/compute/virtual-machine/main.json | 4398 ----------------- .../modules/nic-configuration.bicep | 153 - .../modules/protected-item.bicep | 55 - .../tests/e2e/linux.atmg/dependencies.bicep | 86 - .../tests/e2e/linux.atmg/main.test.bicep | 123 - .../e2e/linux.defaults/dependencies.bicep | 86 - .../tests/e2e/linux.defaults/main.test.bicep | 103 - .../tests/e2e/waf-aligned/dependencies.bicep | 267 - .../tests/e2e/waf-aligned/main.test.bicep | 293 -- .../e2e/windows.defaults/dependencies.bicep | 30 - .../e2e/windows.defaults/main.test.bicep | 86 - .../tests/e2e/windows.max/dependencies.bicep | 310 -- .../tests/e2e/windows.max/main.test.bicep | 331 -- .../e2e/windows.ssecmk/dependencies.bicep | 92 - .../tests/e2e/windows.ssecmk/main.test.bicep | 105 - avm/res/compute/virtual-machine/version.json | 7 - 22 files changed, 7853 deletions(-) delete mode 100644 .github/workflows/avm.res.storage.storage-account.yml delete mode 100644 .github/workflows/avm.res.virtual-machine-images.image-template.yml delete mode 100644 avm/res/compute/virtual-machine/extension/README.md delete mode 100644 avm/res/compute/virtual-machine/extension/main.bicep delete mode 100644 avm/res/compute/virtual-machine/extension/main.json delete mode 100644 avm/res/compute/virtual-machine/main.bicep delete mode 100644 avm/res/compute/virtual-machine/main.json delete mode 100644 avm/res/compute/virtual-machine/modules/nic-configuration.bicep delete mode 100644 avm/res/compute/virtual-machine/modules/protected-item.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep delete mode 100644 avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep delete mode 100644 avm/res/compute/virtual-machine/version.json diff --git a/.github/workflows/avm.res.storage.storage-account.yml b/.github/workflows/avm.res.storage.storage-account.yml deleted file mode 100644 index 061ef0be68..0000000000 --- a/.github/workflows/avm.res.storage.storage-account.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: "avm.res.storage.storage-account" - -on: - schedule: - - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) - workflow_dispatch: - inputs: - staticValidation: - type: boolean - description: "Execute static validation" - required: false - default: true - deploymentValidation: - type: boolean - description: "Execute deployment validation" - required: false - default: true - removeDeployment: - type: boolean - description: "Remove deployed module" - required: false - default: true - - push: - branches: - - main - paths: - - ".github/actions/templates/avm-**" - - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.storage.storage-account.yml" - - "avm/res/storage/storage-account/**" - - "avm/utilities/pipelines/**" - - "!*/**/README.md" - -env: - modulePath: "avm/res/storage/storage-account" - workflowPath: ".github/workflows/avm.res.storage.storage-account.yml" - -concurrency: - group: ${{ github.workflow }} - -jobs: - ########################### - # Initialize pipeline # - ########################### - job_initialize_pipeline: - runs-on: ubuntu-20.04 - name: "Initialize pipeline" - steps: - - name: "Checkout" - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: "Set input parameters to output variables" - id: get-workflow-param - uses: ./.github/actions/templates/avm-getWorkflowInput - with: - workflowPath: "${{ env.workflowPath}}" - - name: "Get module test file paths" - id: get-module-test-file-paths - uses: ./.github/actions/templates/avm-getModuleTestFiles - with: - modulePath: "${{ env.modulePath }}" - outputs: - workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} - moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} - psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} - modulePath: "${{ env.modulePath }}" - - ############################## - # Call reusable workflow # - ############################## - call-workflow-passing-data: - name: "Run" - needs: - - job_initialize_pipeline - uses: ./.github/workflows/avm.template.module.yml - with: - workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" - moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" - psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" - modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" - secrets: inherit diff --git a/.github/workflows/avm.res.virtual-machine-images.image-template.yml b/.github/workflows/avm.res.virtual-machine-images.image-template.yml deleted file mode 100644 index 37bb62af5e..0000000000 --- a/.github/workflows/avm.res.virtual-machine-images.image-template.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: "avm.res.virtual-machine-images.image-template" - -on: - schedule: - - cron: "0 12 1/15 * *" # Bi-Weekly Test (on 1st & 15th of month) - workflow_dispatch: - inputs: - staticValidation: - type: boolean - description: "Execute static validation" - required: false - default: true - deploymentValidation: - type: boolean - description: "Execute deployment validation" - required: false - default: true - removeDeployment: - type: boolean - description: "Remove deployed module" - required: false - default: true - - push: - branches: - - main - paths: - - ".github/actions/templates/avm-**" - - ".github/workflows/avm.template.module.yml" - - ".github/workflows/avm.res.virtual-machine-images.image-template.yml" - - "avm/res/virtual-machine-images/image-template/**" - - "avm/utilities/pipelines/**" - - "!*/**/README.md" - -env: - modulePath: "avm/res/virtual-machine-images/image-template" - workflowPath: ".github/workflows/avm.res.virtual-machine-images.image-template.yml" - -concurrency: - group: ${{ github.workflow }} - -jobs: - ########################### - # Initialize pipeline # - ########################### - job_initialize_pipeline: - runs-on: ubuntu-20.04 - name: "Initialize pipeline" - steps: - - name: "Checkout" - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: "Set input parameters to output variables" - id: get-workflow-param - uses: ./.github/actions/templates/avm-getWorkflowInput - with: - workflowPath: "${{ env.workflowPath}}" - - name: "Get module test file paths" - id: get-module-test-file-paths - uses: ./.github/actions/templates/avm-getModuleTestFiles - with: - modulePath: "${{ env.modulePath }}" - outputs: - workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }} - moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} - psRuleModuleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.psRuleModuleTestFilePaths }} - modulePath: "${{ env.modulePath }}" - - ############################## - # Call reusable workflow # - ############################## - call-workflow-passing-data: - name: "Run" - needs: - - job_initialize_pipeline - uses: ./.github/workflows/avm.template.module.yml - with: - workflowInput: "${{ needs.job_initialize_pipeline.outputs.workflowInput }}" - moduleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.moduleTestFilePaths }}" - psRuleModuleTestFilePaths: "${{ needs.job_initialize_pipeline.outputs.psRuleModuleTestFilePaths }}" - modulePath: "${{ needs.job_initialize_pipeline.outputs.modulePath}}" - secrets: inherit diff --git a/avm/res/compute/virtual-machine/extension/README.md b/avm/res/compute/virtual-machine/extension/README.md deleted file mode 100644 index dccac4e45c..0000000000 --- a/avm/res/compute/virtual-machine/extension/README.md +++ /dev/null @@ -1,156 +0,0 @@ -# Virtual Machine Extensions `[Microsoft.Compute/virtualMachines/extensions]` - -This module deploys a Virtual Machine Extension. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.Compute/virtualMachines/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines/extensions) | - -## Parameters - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`autoUpgradeMinorVersion`](#parameter-autoupgrademinorversion) | bool | Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true. | -| [`enableAutomaticUpgrade`](#parameter-enableautomaticupgrade) | bool | Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available. | -| [`name`](#parameter-name) | string | The name of the virtual machine extension. | -| [`publisher`](#parameter-publisher) | string | The name of the extension handler publisher. | -| [`type`](#parameter-type) | string | Specifies the type of the extension; an example is "CustomScriptExtension". | -| [`typeHandlerVersion`](#parameter-typehandlerversion) | string | Specifies the version of the script handler. | - -**Conditional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`virtualMachineName`](#parameter-virtualmachinename) | string | The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`forceUpdateTag`](#parameter-forceupdatetag) | string | How the extension handler should be forced to update even if the extension configuration has not changed. | -| [`location`](#parameter-location) | string | The location the extension is deployed to. | -| [`protectedSettings`](#parameter-protectedsettings) | secureObject | Any object that contains the extension specific protected settings. | -| [`settings`](#parameter-settings) | object | Any object that contains the extension specific settings. | -| [`supressFailures`](#parameter-supressfailures) | bool | Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false. | -| [`tags`](#parameter-tags) | object | Tags of the resource. | - -### Parameter: `autoUpgradeMinorVersion` - -Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true. - -- Required: Yes -- Type: bool - -### Parameter: `enableAutomaticUpgrade` - -Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available. - -- Required: Yes -- Type: bool - -### Parameter: `name` - -The name of the virtual machine extension. - -- Required: Yes -- Type: string - -### Parameter: `publisher` - -The name of the extension handler publisher. - -- Required: Yes -- Type: string - -### Parameter: `type` - -Specifies the type of the extension; an example is "CustomScriptExtension". - -- Required: Yes -- Type: string - -### Parameter: `typeHandlerVersion` - -Specifies the version of the script handler. - -- Required: Yes -- Type: string - -### Parameter: `virtualMachineName` - -The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment. - -- Required: Yes -- Type: string - -### Parameter: `forceUpdateTag` - -How the extension handler should be forced to update even if the extension configuration has not changed. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `location` - -The location the extension is deployed to. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - -### Parameter: `protectedSettings` - -Any object that contains the extension specific protected settings. - -- Required: No -- Type: secureObject -- Default: `{}` - -### Parameter: `settings` - -Any object that contains the extension specific settings. - -- Required: No -- Type: object -- Default: `{}` - -### Parameter: `supressFailures` - -Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `tags` - -Tags of the resource. - -- Required: No -- Type: object - - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `location` | string | The location the resource was deployed into. | -| `name` | string | The name of the extension. | -| `resourceGroupName` | string | The name of the Resource Group the extension was created in. | -| `resourceId` | string | The resource ID of the extension. | - -## Cross-referenced modules - -_None_ diff --git a/avm/res/compute/virtual-machine/extension/main.bicep b/avm/res/compute/virtual-machine/extension/main.bicep deleted file mode 100644 index 359f99cffd..0000000000 --- a/avm/res/compute/virtual-machine/extension/main.bicep +++ /dev/null @@ -1,77 +0,0 @@ -metadata name = 'Virtual Machine Extensions' -metadata description = 'This module deploys a Virtual Machine Extension.' -metadata owner = 'Azure/module-maintainers' - -@description('Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment.') -param virtualMachineName string - -@description('Required. The name of the virtual machine extension.') -param name string - -@description('Optional. The location the extension is deployed to.') -param location string = resourceGroup().location - -@description('Required. The name of the extension handler publisher.') -param publisher string - -@description('Required. Specifies the type of the extension; an example is "CustomScriptExtension".') -param type string - -@description('Required. Specifies the version of the script handler.') -param typeHandlerVersion string - -@description('Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true.') -param autoUpgradeMinorVersion bool - -@description('Optional. How the extension handler should be forced to update even if the extension configuration has not changed.') -param forceUpdateTag string? - -@description('Optional. Any object that contains the extension specific settings.') -param settings object? - -@description('Optional. Any object that contains the extension specific protected settings.') -@secure() -param protectedSettings object? - -@description('Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false.') -param supressFailures bool = false - -@description('Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available.') -param enableAutomaticUpgrade bool - -@description('Optional. Tags of the resource.') -param tags object? - -resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-11-01' existing = { - name: virtualMachineName -} - -resource extension 'Microsoft.Compute/virtualMachines/extensions@2022-11-01' = { - name: name - parent: virtualMachine - location: location - tags: tags - properties: { - publisher: publisher - type: type - typeHandlerVersion: typeHandlerVersion - autoUpgradeMinorVersion: autoUpgradeMinorVersion - enableAutomaticUpgrade: enableAutomaticUpgrade - forceUpdateTag:forceUpdateTag - settings: settings - protectedSettings: protectedSettings - suppressFailures: supressFailures - } -} - -@description('The name of the extension.') -output name string = extension.name - -@description('The resource ID of the extension.') -output resourceId string = extension.id - -@description('The name of the Resource Group the extension was created in.') -output resourceGroupName string = resourceGroup().name - -@description('The location the resource was deployed into.') -output location string = extension.location diff --git a/avm/res/compute/virtual-machine/extension/main.json b/avm/res/compute/virtual-machine/extension/main.json deleted file mode 100644 index a078645aa8..0000000000 --- a/avm/res/compute/virtual-machine/extension/main.json +++ /dev/null @@ -1,160 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "9445653680126696241" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "defaultValue": {}, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "defaultValue": {}, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[if(not(empty(parameters('forceUpdateTag'))), parameters('forceUpdateTag'), null())]", - "settings": "[if(not(empty(parameters('settings'))), parameters('settings'), null())]", - "protectedSettings": "[if(not(empty(parameters('protectedSettings'))), parameters('protectedSettings'), null())]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } -} \ No newline at end of file diff --git a/avm/res/compute/virtual-machine/main.bicep b/avm/res/compute/virtual-machine/main.bicep deleted file mode 100644 index 592f78b862..0000000000 --- a/avm/res/compute/virtual-machine/main.bicep +++ /dev/null @@ -1,769 +0,0 @@ -metadata name = 'Virtual Machines' -metadata description = 'This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs.' -metadata owner = 'Azure/module-maintainers' - -// Main resource -@description('Required. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory.') -param name string - -@description('Optional. Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name.') -param computerName string = name - -@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 priority 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. The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = "True".') -param managedIdentities managedIdentitiesType - -@description('Optional. Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled.') -param bootDiagnostics bool = false - -@description('Optional. Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided.') -param bootDiagnosticStorageAccountName string = '' - -@description('Optional. Storage account boot diagnostic base URI.') -param bootDiagnosticStorageAccountUri string = '.blob.${environment().suffixes.storage}/' - -@description('Optional. Resource ID of a proximity placement group.') -param proximityPlacementGroupResourceId string = '' - -@description('Optional. Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set.') -param availabilitySetResourceId 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. 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' - -// 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 name is specified. Password of the user specified in user 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 [AAD Join] extension. Must at least contain the ["enabled": true] property to be executed.') -param extensionAadJoinConfig 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. 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 [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys.') -param extensionAzureDiskEncryptionConfig 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. The lock settings of the service.') -param lock lockType - -@description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType - -@description('Optional. Tags of the resource.') -param tags object? - -@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableTelemetry 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.') -#disable-next-line secure-secrets-in-params // Not a secret -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. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning.') -param enableAutomaticUpdates bool = true - -@description('Optional. VM guest patching orchestration mode. \'AutomaticByOS\' & \'Manual\' are for Windows only, \'ImageDefault\' for Linux only. Refer to \'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching\'.') -@allowed([ - 'AutomaticByPlatform' - 'AutomaticByOS' - 'Manual' - 'ImageDefault' - '' -]) -param patchMode string = '' - -@description('Optional. VM guest patching assessment mode. Set it to \'AutomaticByPlatform\' to enable automatically check for updates every 24 hours.') -@allowed([ - 'AutomaticByPlatform' - 'ImageDefault' -]) -param patchAssessmentMode string = 'ImageDefault' - -@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 XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied.') -param additionalUnattendContent array = [] - -@description('Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object.') -param winRM array = [] - -@description('Required. The configuration profile of automanage.') -@allowed([ - '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' - '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' - '' -]) -param configurationProfile string = '' - -var publicKeysFormatted = [for publicKey in publicKeys: { - path: publicKey.path - keyData: publicKey.keyData -}] - -var linuxConfiguration = { - disablePasswordAuthentication: disablePasswordAuthentication - ssh: { - publicKeys: publicKeysFormatted - } - provisionVMAgent: provisionVMAgent - patchSettings: (provisionVMAgent && (patchMode =~ 'AutomaticByPlatform' || patchMode =~ 'ImageDefault')) ? { - patchMode: patchMode - assessmentMode: patchAssessmentMode - } : null -} - -var windowsConfiguration = { - provisionVMAgent: provisionVMAgent - enableAutomaticUpdates: enableAutomaticUpdates - patchSettings: (provisionVMAgent && (patchMode =~ 'AutomaticByPlatform' || patchMode =~ 'AutomaticByOS' || patchMode =~ 'Manual')) ? { - patchMode: patchMode - assessmentMode: patchAssessmentMode - } : null - timeZone: empty(timeZone) ? null : timeZone - additionalUnattendContent: empty(additionalUnattendContent) ? null : additionalUnattendContent - winRM: !empty(winRM) ? { - listeners: winRM - } : null -} - -var accountSasProperties = { - signedServices: 'b' - signedPermission: 'r' - signedExpiry: dateTimeAdd(baseTime, sasTokenValidityLength) - signedResourceTypes: 'o' - signedProtocol: 'https' -} - -var formattedUserAssignedIdentities = reduce(map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), {}, (cur, next) => union(cur, next)) // Converts the flat array to an object like { '${id1}': {}, '${id2}': {} } - -// If AADJoin Extension is enabled then we automatically enable SystemAssigned (required by AADJoin), otherwise we follow the usual logic. -var identity = !empty(managedIdentities) ? { - type: (extensionAadJoinConfig.enabled ? true : (managedIdentities.?systemAssigned ?? false)) ? (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'SystemAssigned,UserAssigned' : 'SystemAssigned') : (!empty(managedIdentities.?userAssignedResourceIds ?? {}) ? 'UserAssigned' : null) - userAssignedIdentities: !empty(formattedUserAssignedIdentities) ? formattedUserAssignedIdentities : null -} : null - -var builtInRoleNames = { - Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Data Operator for Managed Disks': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e') - 'Desktop Virtualization Power On Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33') - 'Desktop Virtualization Power On Off Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e') - 'Desktop Virtualization Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c') - 'DevTest Labs User': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64') - 'Disk Backup Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24') - 'Disk Pool Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840') - 'Disk Restore Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13') - 'Disk Snapshot Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce') - Owner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - Reader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') - 'Virtual Machine Administrator Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4') - 'Virtual Machine Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c') - 'Virtual Machine User Login': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52') - 'VM Scanner Operator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd') -} - -resource avmTelemetry 'Microsoft.Resources/deployments@2023-07-01' = if (enableTelemetry) { - name: '46d3xbcp.res.compute-virtualmachine.${replace('-..--..-', '.', '-')}.${substring(uniqueString(deployment().name, location), 0, 4)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - outputs: { - telemetry: { - type: 'String' - value: 'For more information, see https://aka.ms/avm/TelemetryInfo' - } - } - } - } -} - -module vm_nic 'modules/nic-configuration.bicep' = [for (nicConfiguration, index) in nicConfigurations: { - name: '${uniqueString(deployment().name, location)}-VM-Nic-${index}' - params: { - networkInterfaceName: '${name}${nicConfiguration.nicSuffix}' - virtualMachineName: name - location: location - enableIPForwarding: contains(nicConfiguration, 'enableIPForwarding') ? (!empty(nicConfiguration.enableIPForwarding) ? nicConfiguration.enableIPForwarding : false) : false - enableAcceleratedNetworking: contains(nicConfiguration, 'enableAcceleratedNetworking') ? nicConfiguration.enableAcceleratedNetworking : true - dnsServers: contains(nicConfiguration, 'dnsServers') ? (!empty(nicConfiguration.dnsServers) ? nicConfiguration.dnsServers : []) : [] - networkSecurityGroupResourceId: contains(nicConfiguration, 'networkSecurityGroupResourceId') ? nicConfiguration.networkSecurityGroupResourceId : '' - ipConfigurations: nicConfiguration.ipConfigurations - lock: nicConfiguration.?lock ?? lock - tags: nicConfiguration.?tags ?? tags - diagnosticSettings: nicConfiguration.?diagnosticSettings - roleAssignments: nicConfiguration.?roleAssignments - enableTelemetry: nicConfiguration.?enableTelemetry ?? enableTelemetry - } -}] - -resource vm 'Microsoft.Compute/virtualMachines@2022-11-01' = { - name: name - location: location - identity: identity - tags: tags - zones: availabilityZone != 0 ? array(availabilityZone) : null - plan: !empty(plan) ? plan : null - properties: { - hardwareProfile: { - vmSize: vmSize - } - securityProfile: { - encryptionAtHost: encryptionAtHost ? encryptionAtHost : null - securityType: securityType - uefiSettings: securityType == 'TrustedLaunch' ? { - secureBootEnabled: secureBootEnabled - vTpmEnabled: vTpmEnabled - } : null - } - storageProfile: { - imageReference: imageReference - osDisk: { - name: '${name}-disk-os-01' - createOption: contains(osDisk, 'createOption') ? osDisk.createOption : 'FromImage' - deleteOption: contains(osDisk, 'deleteOption') ? osDisk.deleteOption : 'Delete' - diskSizeGB: osDisk.diskSizeGB - caching: contains(osDisk, 'caching') ? osDisk.caching : 'ReadOnly' - managedDisk: { - storageAccountType: osDisk.managedDisk.storageAccountType - diskEncryptionSet: contains(osDisk.managedDisk, 'diskEncryptionSet') ? { - id: osDisk.managedDisk.diskEncryptionSet.id - } : null - } - } - dataDisks: [for (dataDisk, index) in dataDisks: { - lun: index - name: '${name}-disk-data-${padLeft((index + 1), 2, '0')}' - diskSizeGB: dataDisk.diskSizeGB - createOption: contains(dataDisk, 'createOption') ? dataDisk.createOption : 'Empty' - deleteOption: contains(dataDisk, 'deleteOption') ? dataDisk.deleteOption : 'Delete' - caching: contains(dataDisk, 'caching') ? dataDisk.caching : 'ReadOnly' - managedDisk: { - storageAccountType: dataDisk.managedDisk.storageAccountType - diskEncryptionSet: contains(dataDisk.managedDisk, 'diskEncryptionSet') ? { - id: dataDisk.managedDisk.diskEncryptionSet.id - } : null - } - }] - } - additionalCapabilities: { - ultraSSDEnabled: ultraSSDEnabled - } - osProfile: { - computerName: computerName - adminUsername: adminUsername - adminPassword: adminPassword - customData: !empty(customData) ? base64(customData) : null - windowsConfiguration: osType == 'Windows' ? windowsConfiguration : null - linuxConfiguration: osType == 'Linux' ? linuxConfiguration : null - secrets: certificatesToBeInstalled - allowExtensionOperations: allowExtensionOperations - } - networkProfile: { - networkInterfaces: [for (nicConfiguration, index) in nicConfigurations: { - properties: { - deleteOption: contains(nicConfiguration, 'deleteOption') ? nicConfiguration.deleteOption : 'Delete' - primary: index == 0 ? true : false - } - #disable-next-line use-resource-id-functions // It's a reference from inside a loop which makes resolving it using a resource reference particulary difficult. - id: az.resourceId('Microsoft.Network/networkInterfaces', '${name}${nicConfiguration.nicSuffix}') - }] - } - diagnosticsProfile: { - bootDiagnostics: { - enabled: !empty(bootDiagnosticStorageAccountName) ? true : bootDiagnostics - storageUri: !empty(bootDiagnosticStorageAccountName) ? 'https://${bootDiagnosticStorageAccountName}${bootDiagnosticStorageAccountUri}' : null - } - } - availabilitySet: !empty(availabilitySetResourceId) ? { - id: availabilitySetResourceId - } : null - proximityPlacementGroup: !empty(proximityPlacementGroupResourceId) ? { - id: proximityPlacementGroupResourceId - } : null - priority: priority - evictionPolicy: enableEvictionPolicy ? 'Deallocate' : null - billingProfile: !empty(priority) && !empty(maxPriceForLowPriorityVm) ? { - maxPrice: maxPriceForLowPriorityVm - } : null - host: !empty(dedicatedHostId) ? { - id: dedicatedHostId - } : null - licenseType: !empty(licenseType) ? licenseType : null - } - dependsOn: [ - vm_nic - ] -} - -resource vm_configurationProfileAssignment 'Microsoft.Automanage/configurationProfileAssignments@2021-04-30-preview' = if (!empty(configurationProfile)) { - name: 'default' - properties: { - configurationProfile: configurationProfile - } - scope: vm -} - -module vm_aadJoinExtension 'extension/main.bicep' = if (extensionAadJoinConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-AADLogin' - params: { - virtualMachineName: vm.name - name: 'AADLogin' - location: location - publisher: 'Microsoft.Azure.ActiveDirectory' - type: osType == 'Windows' ? 'AADLoginForWindows' : 'AADSSHLoginforLinux' - typeHandlerVersion: contains(extensionAadJoinConfig, 'typeHandlerVersion') ? extensionAadJoinConfig.typeHandlerVersion : '1.0' - autoUpgradeMinorVersion: contains(extensionAadJoinConfig, 'autoUpgradeMinorVersion') ? extensionAadJoinConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionAadJoinConfig, 'enableAutomaticUpgrade') ? extensionAadJoinConfig.enableAutomaticUpgrade : false - settings: contains(extensionAadJoinConfig, 'settings') ? extensionAadJoinConfig.settings : {} - tags: extensionAadJoinConfig.?tags ?? tags - } -} - -module vm_domainJoinExtension 'extension/main.bicep' = if (extensionDomainJoinConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-DomainJoin' - params: { - virtualMachineName: vm.name - name: 'DomainJoin' - location: location - publisher: 'Microsoft.Compute' - type: 'JsonADDomainExtension' - typeHandlerVersion: contains(extensionDomainJoinConfig, 'typeHandlerVersion') ? extensionDomainJoinConfig.typeHandlerVersion : '1.3' - autoUpgradeMinorVersion: contains(extensionDomainJoinConfig, 'autoUpgradeMinorVersion') ? extensionDomainJoinConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionDomainJoinConfig, 'enableAutomaticUpgrade') ? extensionDomainJoinConfig.enableAutomaticUpgrade : false - settings: extensionDomainJoinConfig.settings - tags: extensionDomainJoinConfig.?tags ?? tags - protectedSettings: { - Password: extensionDomainJoinPassword - } - } -} - -module vm_microsoftAntiMalwareExtension 'extension/main.bicep' = if (extensionAntiMalwareConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-MicrosoftAntiMalware' - params: { - virtualMachineName: vm.name - name: 'MicrosoftAntiMalware' - location: location - publisher: 'Microsoft.Azure.Security' - type: 'IaaSAntimalware' - typeHandlerVersion: contains(extensionAntiMalwareConfig, 'typeHandlerVersion') ? extensionAntiMalwareConfig.typeHandlerVersion : '1.3' - autoUpgradeMinorVersion: contains(extensionAntiMalwareConfig, 'autoUpgradeMinorVersion') ? extensionAntiMalwareConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionAntiMalwareConfig, 'enableAutomaticUpgrade') ? extensionAntiMalwareConfig.enableAutomaticUpgrade : false - settings: extensionAntiMalwareConfig.settings - tags: extensionAntiMalwareConfig.?tags ?? tags - } -} - -// resource vm_logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' existing = if (!empty(monitoringWorkspaceId)) { -// name: last(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : 'law'), '/'))! -// scope: az.resourceGroup(split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '//'), '/')[2], split((!empty(monitoringWorkspaceId) ? monitoringWorkspaceId : '////'), '/')[4]) -// } - -module vm_azureMonitoringAgentExtension 'extension/main.bicep' = if (extensionMonitoringAgentConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-AzureMonitoringAgent' - params: { - virtualMachineName: vm.name - name: 'AzureMonitoringAgent' - location: location - publisher: 'Microsoft.Azure.Monitor' - type: osType == 'Windows' ? 'AzureMonitorWindowsAgent' : 'AzureMonitorLinuxAgent' - typeHandlerVersion: contains(extensionMonitoringAgentConfig, 'typeHandlerVersion') ? extensionMonitoringAgentConfig.typeHandlerVersion : (osType == 'Windows' ? '1.0' : '1.21') - autoUpgradeMinorVersion: contains(extensionMonitoringAgentConfig, 'autoUpgradeMinorVersion') ? extensionMonitoringAgentConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionMonitoringAgentConfig, 'enableAutomaticUpgrade') ? extensionMonitoringAgentConfig.enableAutomaticUpgrade : true - tags: extensionMonitoringAgentConfig.?tags ?? tags - } -} - -module vm_dependencyAgentExtension 'extension/main.bicep' = if (extensionDependencyAgentConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-DependencyAgent' - params: { - virtualMachineName: vm.name - name: 'DependencyAgent' - location: location - publisher: 'Microsoft.Azure.Monitoring.DependencyAgent' - type: osType == 'Windows' ? 'DependencyAgentWindows' : 'DependencyAgentLinux' - typeHandlerVersion: contains(extensionDependencyAgentConfig, 'typeHandlerVersion') ? extensionDependencyAgentConfig.typeHandlerVersion : '9.5' - autoUpgradeMinorVersion: contains(extensionDependencyAgentConfig, 'autoUpgradeMinorVersion') ? extensionDependencyAgentConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionDependencyAgentConfig, 'enableAutomaticUpgrade') ? extensionDependencyAgentConfig.enableAutomaticUpgrade : true - tags: extensionDependencyAgentConfig.?tags ?? tags - } -} - -module vm_networkWatcherAgentExtension 'extension/main.bicep' = if (extensionNetworkWatcherAgentConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-NetworkWatcherAgent' - params: { - virtualMachineName: vm.name - name: 'NetworkWatcherAgent' - location: location - publisher: 'Microsoft.Azure.NetworkWatcher' - type: osType == 'Windows' ? 'NetworkWatcherAgentWindows' : 'NetworkWatcherAgentLinux' - typeHandlerVersion: contains(extensionNetworkWatcherAgentConfig, 'typeHandlerVersion') ? extensionNetworkWatcherAgentConfig.typeHandlerVersion : '1.4' - autoUpgradeMinorVersion: contains(extensionNetworkWatcherAgentConfig, 'autoUpgradeMinorVersion') ? extensionNetworkWatcherAgentConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionNetworkWatcherAgentConfig, 'enableAutomaticUpgrade') ? extensionNetworkWatcherAgentConfig.enableAutomaticUpgrade : false - tags: extensionNetworkWatcherAgentConfig.?tags ?? tags - } -} - -module vm_desiredStateConfigurationExtension 'extension/main.bicep' = if (extensionDSCConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-DesiredStateConfiguration' - params: { - virtualMachineName: vm.name - name: 'DesiredStateConfiguration' - location: location - publisher: 'Microsoft.Powershell' - type: 'DSC' - typeHandlerVersion: contains(extensionDSCConfig, 'typeHandlerVersion') ? extensionDSCConfig.typeHandlerVersion : '2.77' - autoUpgradeMinorVersion: contains(extensionDSCConfig, 'autoUpgradeMinorVersion') ? extensionDSCConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionDSCConfig, 'enableAutomaticUpgrade') ? extensionDSCConfig.enableAutomaticUpgrade : false - settings: contains(extensionDSCConfig, 'settings') ? extensionDSCConfig.settings : {} - tags: extensionDSCConfig.?tags ?? tags - protectedSettings: contains(extensionDSCConfig, 'protectedSettings') ? extensionDSCConfig.protectedSettings : {} - } -} - -module vm_customScriptExtension 'extension/main.bicep' = if (extensionCustomScriptConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-CustomScriptExtension' - params: { - virtualMachineName: vm.name - name: 'CustomScriptExtension' - location: location - publisher: osType == 'Windows' ? 'Microsoft.Compute' : 'Microsoft.Azure.Extensions' - type: osType == 'Windows' ? 'CustomScriptExtension' : 'CustomScript' - typeHandlerVersion: contains(extensionCustomScriptConfig, 'typeHandlerVersion') ? extensionCustomScriptConfig.typeHandlerVersion : (osType == 'Windows' ? '1.10' : '2.1') - autoUpgradeMinorVersion: contains(extensionCustomScriptConfig, 'autoUpgradeMinorVersion') ? extensionCustomScriptConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionCustomScriptConfig, 'enableAutomaticUpgrade') ? extensionCustomScriptConfig.enableAutomaticUpgrade : false - settings: { - fileUris: [for fileData in extensionCustomScriptConfig.fileData: contains(fileData, 'storageAccountId') ? '${fileData.uri}?${listAccountSas(fileData.storageAccountId, '2019-04-01', accountSasProperties).accountSasToken}' : fileData.uri] - } - tags: extensionCustomScriptConfig.?tags ?? tags - protectedSettings: extensionCustomScriptProtectedSetting - } - dependsOn: [ - vm_desiredStateConfigurationExtension - ] -} - -module vm_azureDiskEncryptionExtension 'extension/main.bicep' = if (extensionAzureDiskEncryptionConfig.enabled) { - name: '${uniqueString(deployment().name, location)}-VM-AzureDiskEncryption' - params: { - virtualMachineName: vm.name - name: 'AzureDiskEncryption' - location: location - publisher: 'Microsoft.Azure.Security' - type: osType == 'Windows' ? 'AzureDiskEncryption' : 'AzureDiskEncryptionForLinux' - typeHandlerVersion: contains(extensionAzureDiskEncryptionConfig, 'typeHandlerVersion') ? extensionAzureDiskEncryptionConfig.typeHandlerVersion : (osType == 'Windows' ? '2.2' : '1.1') - autoUpgradeMinorVersion: contains(extensionAzureDiskEncryptionConfig, 'autoUpgradeMinorVersion') ? extensionAzureDiskEncryptionConfig.autoUpgradeMinorVersion : true - enableAutomaticUpgrade: contains(extensionAzureDiskEncryptionConfig, 'enableAutomaticUpgrade') ? extensionAzureDiskEncryptionConfig.enableAutomaticUpgrade : false - forceUpdateTag: contains(extensionAzureDiskEncryptionConfig, 'forceUpdateTag') ? extensionAzureDiskEncryptionConfig.forceUpdateTag : '1.0' - settings: extensionAzureDiskEncryptionConfig.settings - tags: extensionAzureDiskEncryptionConfig.?tags ?? tags - } - dependsOn: [ - vm_customScriptExtension - vm_azureMonitoringAgentExtension - ] -} - -module vm_backup 'modules/protected-item.bicep' = if (!empty(backupVaultName)) { - name: '${uniqueString(deployment().name, location)}-VM-Backup' - params: { - name: 'vm;iaasvmcontainerv2;${resourceGroup().name};${vm.name}' - location: location - policyId: az.resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', backupVaultName, backupPolicyName) - protectedItemType: 'Microsoft.Compute/virtualMachines' - protectionContainerName: 'iaasvmcontainer;iaasvmcontainerv2;${resourceGroup().name};${vm.name}' - recoveryVaultName: backupVaultName - sourceResourceId: vm.id - } - scope: az.resourceGroup(backupVaultResourceGroup) - dependsOn: [ - vm_aadJoinExtension - vm_domainJoinExtension - vm_azureMonitoringAgentExtension - vm_microsoftAntiMalwareExtension - vm_networkWatcherAgentExtension - vm_dependencyAgentExtension - vm_desiredStateConfigurationExtension - vm_customScriptExtension - ] -} - -resource vm_lock 'Microsoft.Authorization/locks@2020-05-01' = if (!empty(lock ?? {}) && lock.?kind != 'None') { - name: lock.?name ?? 'lock-${name}' - properties: { - level: lock.?kind ?? '' - notes: lock.?kind == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot delete or modify the resource or child resources.' - } - scope: vm -} - -resource vm_roleAssignments 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (roleAssignment, index) in (roleAssignments ?? []): { - name: guid(vm.id, roleAssignment.principalId, roleAssignment.roleDefinitionIdOrName) - properties: { - roleDefinitionId: contains(builtInRoleNames, roleAssignment.roleDefinitionIdOrName) ? builtInRoleNames[roleAssignment.roleDefinitionIdOrName] : contains(roleAssignment.roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/') ? roleAssignment.roleDefinitionIdOrName : subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleAssignment.roleDefinitionIdOrName) - principalId: roleAssignment.principalId - description: roleAssignment.?description - principalType: roleAssignment.?principalType - condition: roleAssignment.?condition - conditionVersion: !empty(roleAssignment.?condition) ? (roleAssignment.?conditionVersion ?? '2.0') : null // Must only be set if condtion is set - delegatedManagedIdentityResourceId: roleAssignment.?delegatedManagedIdentityResourceId - } - scope: vm -}] - -@description('The name of the VM.') -output name string = vm.name - -@description('The resource ID of the VM.') -output resourceId string = vm.id - -@description('The name of the resource group the VM was created in.') -output resourceGroupName string = resourceGroup().name - -@description('The principal ID of the system assigned identity.') -output systemAssignedMIPrincipalId string = (managedIdentities.?systemAssigned ?? false) && contains(vm.identity, 'principalId') ? vm.identity.principalId : '' - -@description('The location the resource was deployed into.') -output location string = vm.location - -// =============== // -// Definitions // -// =============== // - -type managedIdentitiesType = { - @description('Optional. Enables system assigned managed identity on the resource.') - systemAssigned: bool? - - @description('Optional. The resource ID(s) to assign to the resource.') - userAssignedResourceIds: string[]? -}? - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type roleAssignmentType = { - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \'AllLogs\' to collect all logs.') - categoryGroup: string? - }[]? - - @description('Optional. The name of metrics that will be streamed. "allMetrics" includes all possible metrics for the resource. Set to \'\' to disable metric collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to \'AllMetrics\' to collect all metrics.') - category: string - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') - workspaceResourceId: string? - - @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? diff --git a/avm/res/compute/virtual-machine/main.json b/avm/res/compute/virtual-machine/main.json deleted file mode 100644 index 9f8f0c17f3..0000000000 --- a/avm/res/compute/virtual-machine/main.json +++ /dev/null @@ -1,4398 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "3906813880748579145" - }, - "name": "Virtual Machines", - "description": "This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs.", - "owner": "Azure/module-maintainers" - }, - "definitions": { - "managedIdentitiesType": { - "type": "object", - "properties": { - "systemAssigned": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." - } - }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." - } - } - }, - "nullable": true - }, - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to 'AllLogs' to collect all logs." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to 'AllMetrics' to collect all metrics." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "metadata": { - "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory." - } - }, - "computerName": { - "type": "string", - "defaultValue": "[parameters('name')]", - "metadata": { - "description": "Optional. Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name." - } - }, - "vmSize": { - "type": "string", - "metadata": { - "description": "Required. Specifies the size for the VMs." - } - }, - "encryptionAtHost": { - "type": "bool", - "defaultValue": true, - "metadata": { - "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." - } - }, - "securityType": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings." - } - }, - "secureBootEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "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." - } - }, - "vTpmEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "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." - } - }, - "imageReference": { - "type": "object", - "metadata": { - "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." - } - }, - "plan": { - "type": "object", - "defaultValue": {}, - "metadata": { - "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." - } - }, - "osDisk": { - "type": "object", - "metadata": { - "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." - } - }, - "dataDisks": { - "type": "array", - "defaultValue": [], - "metadata": { - "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." - } - }, - "ultraSSDEnabled": { - "type": "bool", - "defaultValue": false, - "metadata": { - "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." - } - }, - "adminUsername": { - "type": "securestring", - "metadata": { - "description": "Required. Administrator username." - } - }, - "adminPassword": { - "type": "securestring", - "defaultValue": "", - "metadata": { - "description": "Optional. When specifying a Windows Virtual Machine, this value should be passed." - } - }, - "customData": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format." - } - }, - "certificatesToBeInstalled": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. Specifies set of certificates that should be installed onto the virtual machine." - } - }, - "priority": { - "type": "string", - "defaultValue": "Regular", - "allowedValues": [ - "Regular", - "Low", - "Spot" - ], - "metadata": { - "description": "Optional. Specifies the priority for the virtual machine." - } - }, - "enableEvictionPolicy": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy." - } - }, - "maxPriceForLowPriorityVm": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars." - } - }, - "dedicatedHostId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Specifies resource ID about the dedicated host that the virtual machine resides in." - } - }, - "licenseType": { - "type": "string", - "defaultValue": "", - "allowedValues": [ - "Windows_Client", - "Windows_Server", - "" - ], - "metadata": { - "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." - } - }, - "publicKeys": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. The list of SSH public keys used to authenticate with linux based VMs." - } - }, - "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", - "metadata": { - "description": "Optional. The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = \"True\"." - } - }, - "bootDiagnostics": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled." - } - }, - "bootDiagnosticStorageAccountName": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided." - } - }, - "bootDiagnosticStorageAccountUri": { - "type": "string", - "defaultValue": "[format('.blob.{0}/', environment().suffixes.storage)]", - "metadata": { - "description": "Optional. Storage account boot diagnostic base URI." - } - }, - "proximityPlacementGroupResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Resource ID of a proximity placement group." - } - }, - "availabilitySetResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set." - } - }, - "availabilityZone": { - "type": "int", - "defaultValue": 0, - "allowedValues": [ - 0, - 1, - 2, - 3 - ], - "metadata": { - "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." - } - }, - "nicConfigurations": { - "type": "array", - "metadata": { - "description": "Required. Configures NICs and PIPs." - } - }, - "backupVaultName": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. Recovery service vault name to add VMs to backup." - } - }, - "backupVaultResourceGroup": { - "type": "string", - "defaultValue": "[resourceGroup().name]", - "metadata": { - "description": "Optional. Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default." - } - }, - "backupPolicyName": { - "type": "string", - "defaultValue": "DefaultPolicy", - "metadata": { - "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." - } - }, - "allowExtensionOperations": { - "type": "bool", - "defaultValue": true, - "metadata": { - "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." - } - }, - "extensionDomainJoinPassword": { - "type": "securestring", - "defaultValue": "", - "metadata": { - "description": "Optional. Required if name is specified. Password of the user specified in user parameter." - } - }, - "extensionDomainJoinConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Domain Join] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionAadJoinConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [AAD Join] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionAntiMalwareConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Anti Malware] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionMonitoringAgentConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Monitoring Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionDependencyAgentConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Dependency Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionNetworkWatcherAgentConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Network Watcher Agent] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionAzureDiskEncryptionConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Azure Disk Encryption] extension. Must at least contain the [\"enabled\": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys." - } - }, - "extensionDSCConfig": { - "type": "object", - "defaultValue": { - "enabled": false - }, - "metadata": { - "description": "Optional. The configuration for the [Desired State Configuration] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionCustomScriptConfig": { - "type": "object", - "defaultValue": { - "enabled": false, - "fileData": [] - }, - "metadata": { - "description": "Optional. The configuration for the [Custom Script] extension. Must at least contain the [\"enabled\": true] property to be executed." - } - }, - "extensionCustomScriptProtectedSetting": { - "type": "secureObject", - "defaultValue": {}, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. The lock settings of the service." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } - }, - "baseTime": { - "type": "string", - "defaultValue": "[utcNow('u')]", - "metadata": { - "description": "Generated. Do not provide a value! This date value is used to generate a registration token." - } - }, - "sasTokenValidityLength": { - "type": "string", - "defaultValue": "PT8H", - "metadata": { - "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." - } - }, - "osType": { - "type": "string", - "allowedValues": [ - "Windows", - "Linux" - ], - "metadata": { - "description": "Required. The chosen OS type." - } - }, - "disablePasswordAuthentication": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Specifies whether password authentication should be disabled." - } - }, - "provisionVMAgent": { - "type": "bool", - "defaultValue": true, - "metadata": { - "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." - } - }, - "enableAutomaticUpdates": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning." - } - }, - "patchMode": { - "type": "string", - "defaultValue": "", - "allowedValues": [ - "AutomaticByPlatform", - "AutomaticByOS", - "Manual", - "ImageDefault", - "" - ], - "metadata": { - "description": "Optional. VM guest patching orchestration mode. 'AutomaticByOS' & 'Manual' are for Windows only, 'ImageDefault' for Linux only. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'." - } - }, - "patchAssessmentMode": { - "type": "string", - "defaultValue": "ImageDefault", - "allowedValues": [ - "AutomaticByPlatform", - "ImageDefault" - ], - "metadata": { - "description": "Optional. VM guest patching assessment mode. Set it to 'AutomaticByPlatform' to enable automatically check for updates every 24 hours." - } - }, - "timeZone": { - "type": "string", - "defaultValue": "", - "metadata": { - "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`." - } - }, - "additionalUnattendContent": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. Specifies additional XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied." - } - }, - "winRM": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object." - } - }, - "configurationProfile": { - "type": "string", - "defaultValue": "", - "allowedValues": [ - "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction", - "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest", - "" - ], - "metadata": { - "description": "Required. The configuration profile of automanage." - } - } - }, - "variables": { - "copy": [ - { - "name": "publicKeysFormatted", - "count": "[length(parameters('publicKeys'))]", - "input": { - "path": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].path]", - "keyData": "[parameters('publicKeys')[copyIndex('publicKeysFormatted')].keyData]" - } - } - ], - "linuxConfiguration": { - "disablePasswordAuthentication": "[parameters('disablePasswordAuthentication')]", - "ssh": { - "publicKeys": "[variables('publicKeysFormatted')]" - }, - "provisionVMAgent": "[parameters('provisionVMAgent')]", - "patchSettings": "[if(and(parameters('provisionVMAgent'), or(equals(toLower(parameters('patchMode')), toLower('AutomaticByPlatform')), equals(toLower(parameters('patchMode')), toLower('ImageDefault')))), createObject('patchMode', parameters('patchMode'), 'assessmentMode', parameters('patchAssessmentMode')), null())]" - }, - "windowsConfiguration": { - "provisionVMAgent": "[parameters('provisionVMAgent')]", - "enableAutomaticUpdates": "[parameters('enableAutomaticUpdates')]", - "patchSettings": "[if(and(parameters('provisionVMAgent'), or(or(equals(toLower(parameters('patchMode')), toLower('AutomaticByPlatform')), equals(toLower(parameters('patchMode')), toLower('AutomaticByOS'))), equals(toLower(parameters('patchMode')), toLower('Manual')))), createObject('patchMode', parameters('patchMode'), 'assessmentMode', parameters('patchAssessmentMode')), null())]", - "timeZone": "[if(empty(parameters('timeZone')), null(), parameters('timeZone'))]", - "additionalUnattendContent": "[if(empty(parameters('additionalUnattendContent')), null(), parameters('additionalUnattendContent'))]", - "winRM": "[if(not(empty(parameters('winRM'))), createObject('listeners', parameters('winRM')), null())]" - }, - "accountSasProperties": { - "signedServices": "b", - "signedPermission": "r", - "signedExpiry": "[dateTimeAdd(parameters('baseTime'), parameters('sasTokenValidityLength'))]", - "signedResourceTypes": "o", - "signedProtocol": "https" - }, - "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(if(parameters('extensionAadJoinConfig').enabled, true(), coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false())), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned,UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', null())), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", - "builtInRoleNames": { - "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", - "Data Operator for Managed Disks": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '959f8984-c045-4866-89c7-12bf9737be2e')]", - "Desktop Virtualization Power On Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '489581de-a3bd-480d-9518-53dea7416b33')]", - "Desktop Virtualization Power On Off Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '40c5ff49-9181-41f8-ae61-143b0e78555e')]", - "Desktop Virtualization Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a959dbd1-f747-45e3-8ba6-dd80f235f97c')]", - "DevTest Labs User": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76283e04-6283-4c54-8f91-bcf1374a3c64')]", - "Disk Backup Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24')]", - "Disk Pool Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '60fc6e62-5479-42d4-8bf4-67625fcc2840')]", - "Disk Restore Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b50d9833-a0cb-478e-945f-707fcc997c13')]", - "Disk Snapshot Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7efff54f-a5b4-42b5-a1c5-5411624893ce')]", - "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", - "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", - "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]", - "Virtual Machine Administrator Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c0163c0-47e6-4577-8991-ea5c82e286e4')]", - "Virtual Machine Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '9980e02c-c2be-4d73-94e8-173b1dc7cf3c')]", - "Virtual Machine User Login": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb879df8-f326-4884-b1cf-06f3ad86be52')]", - "VM Scanner Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'd24ecba3-c1f4-40fa-a7bb-4588a071e8fd')]" - } - }, - "resources": { - "avmTelemetry": { - "condition": "[parameters('enableTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.compute-virtualmachine.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [], - "outputs": { - "telemetry": { - "type": "String", - "value": "For more information, see https://aka.ms/avm/TelemetryInfo" - } - } - } - } - }, - "vm": { - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "identity": "[variables('identity')]", - "tags": "[parameters('tags')]", - "zones": "[if(not(equals(parameters('availabilityZone'), 0)), array(parameters('availabilityZone')), null())]", - "plan": "[if(not(empty(parameters('plan'))), parameters('plan'), null())]", - "properties": { - "hardwareProfile": { - "vmSize": "[parameters('vmSize')]" - }, - "securityProfile": { - "encryptionAtHost": "[if(parameters('encryptionAtHost'), parameters('encryptionAtHost'), null())]", - "securityType": "[parameters('securityType')]", - "uefiSettings": "[if(equals(parameters('securityType'), 'TrustedLaunch'), createObject('secureBootEnabled', parameters('secureBootEnabled'), 'vTpmEnabled', parameters('vTpmEnabled')), null())]" - }, - "storageProfile": { - "copy": [ - { - "name": "dataDisks", - "count": "[length(parameters('dataDisks'))]", - "input": { - "lun": "[copyIndex('dataDisks')]", - "name": "[format('{0}-disk-data-{1}', parameters('name'), padLeft(add(copyIndex('dataDisks'), 1), 2, '0'))]", - "diskSizeGB": "[parameters('dataDisks')[copyIndex('dataDisks')].diskSizeGB]", - "createOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'createOption'), parameters('dataDisks')[copyIndex('dataDisks')].createOption, 'Empty')]", - "deleteOption": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'deleteOption'), parameters('dataDisks')[copyIndex('dataDisks')].deleteOption, 'Delete')]", - "caching": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')], 'caching'), parameters('dataDisks')[copyIndex('dataDisks')].caching, 'ReadOnly')]", - "managedDisk": { - "storageAccountType": "[parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.storageAccountType]", - "diskEncryptionSet": "[if(contains(parameters('dataDisks')[copyIndex('dataDisks')].managedDisk, 'diskEncryptionSet'), createObject('id', parameters('dataDisks')[copyIndex('dataDisks')].managedDisk.diskEncryptionSet.id), null())]" - } - } - } - ], - "imageReference": "[parameters('imageReference')]", - "osDisk": { - "name": "[format('{0}-disk-os-01', parameters('name'))]", - "createOption": "[if(contains(parameters('osDisk'), 'createOption'), parameters('osDisk').createOption, 'FromImage')]", - "deleteOption": "[if(contains(parameters('osDisk'), 'deleteOption'), parameters('osDisk').deleteOption, 'Delete')]", - "diskSizeGB": "[parameters('osDisk').diskSizeGB]", - "caching": "[if(contains(parameters('osDisk'), 'caching'), parameters('osDisk').caching, 'ReadOnly')]", - "managedDisk": { - "storageAccountType": "[parameters('osDisk').managedDisk.storageAccountType]", - "diskEncryptionSet": "[if(contains(parameters('osDisk').managedDisk, 'diskEncryptionSet'), createObject('id', parameters('osDisk').managedDisk.diskEncryptionSet.id), null())]" - } - } - }, - "additionalCapabilities": { - "ultraSSDEnabled": "[parameters('ultraSSDEnabled')]" - }, - "osProfile": { - "computerName": "[parameters('computerName')]", - "adminUsername": "[parameters('adminUsername')]", - "adminPassword": "[parameters('adminPassword')]", - "customData": "[if(not(empty(parameters('customData'))), base64(parameters('customData')), null())]", - "windowsConfiguration": "[if(equals(parameters('osType'), 'Windows'), variables('windowsConfiguration'), null())]", - "linuxConfiguration": "[if(equals(parameters('osType'), 'Linux'), variables('linuxConfiguration'), null())]", - "secrets": "[parameters('certificatesToBeInstalled')]", - "allowExtensionOperations": "[parameters('allowExtensionOperations')]" - }, - "networkProfile": { - "copy": [ - { - "name": "networkInterfaces", - "count": "[length(parameters('nicConfigurations'))]", - "input": { - "properties": { - "deleteOption": "[if(contains(parameters('nicConfigurations')[copyIndex('networkInterfaces')], 'deleteOption'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].deleteOption, 'Delete')]", - "primary": "[if(equals(copyIndex('networkInterfaces'), 0), true(), false())]" - }, - "id": "[resourceId('Microsoft.Network/networkInterfaces', format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex('networkInterfaces')].nicSuffix))]" - } - } - ] - }, - "diagnosticsProfile": { - "bootDiagnostics": { - "enabled": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), true(), parameters('bootDiagnostics'))]", - "storageUri": "[if(not(empty(parameters('bootDiagnosticStorageAccountName'))), format('https://{0}{1}', parameters('bootDiagnosticStorageAccountName'), parameters('bootDiagnosticStorageAccountUri')), null())]" - } - }, - "availabilitySet": "[if(not(empty(parameters('availabilitySetResourceId'))), createObject('id', parameters('availabilitySetResourceId')), null())]", - "proximityPlacementGroup": "[if(not(empty(parameters('proximityPlacementGroupResourceId'))), createObject('id', parameters('proximityPlacementGroupResourceId')), null())]", - "priority": "[parameters('priority')]", - "evictionPolicy": "[if(parameters('enableEvictionPolicy'), 'Deallocate', null())]", - "billingProfile": "[if(and(not(empty(parameters('priority'))), not(empty(parameters('maxPriceForLowPriorityVm')))), createObject('maxPrice', parameters('maxPriceForLowPriorityVm')), null())]", - "host": "[if(not(empty(parameters('dedicatedHostId'))), createObject('id', parameters('dedicatedHostId')), null())]", - "licenseType": "[if(not(empty(parameters('licenseType'))), parameters('licenseType'), null())]" - }, - "dependsOn": [ - "vm_nic" - ] - }, - "vm_configurationProfileAssignment": { - "condition": "[not(empty(parameters('configurationProfile')))]", - "type": "Microsoft.Automanage/configurationProfileAssignments", - "apiVersion": "2021-04-30-preview", - "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", - "name": "default", - "properties": { - "configurationProfile": "[parameters('configurationProfile')]" - }, - "dependsOn": [ - "vm" - ] - }, - "vm_lock": { - "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", - "type": "Microsoft.Authorization/locks", - "apiVersion": "2020-05-01", - "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", - "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", - "properties": { - "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", - "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" - }, - "dependsOn": [ - "vm" - ] - }, - "vm_roleAssignments": { - "copy": { - "name": "vm_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" - }, - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.Compute/virtualMachines/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Compute/virtualMachines', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", - "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" - }, - "dependsOn": [ - "vm" - ] - }, - "vm_nic": { - "copy": { - "name": "vm_nic", - "count": "[length(parameters('nicConfigurations'))]" - }, - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-Nic-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "networkInterfaceName": { - "value": "[format('{0}{1}', parameters('name'), parameters('nicConfigurations')[copyIndex()].nicSuffix)]" - }, - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "location": { - "value": "[parameters('location')]" - }, - "enableIPForwarding": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableIPForwarding'), if(not(empty(parameters('nicConfigurations')[copyIndex()].enableIPForwarding)), createObject('value', parameters('nicConfigurations')[copyIndex()].enableIPForwarding), createObject('value', false())), createObject('value', false()))]", - "enableAcceleratedNetworking": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'enableAcceleratedNetworking'), createObject('value', parameters('nicConfigurations')[copyIndex()].enableAcceleratedNetworking), createObject('value', true()))]", - "dnsServers": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'dnsServers'), if(not(empty(parameters('nicConfigurations')[copyIndex()].dnsServers)), createObject('value', parameters('nicConfigurations')[copyIndex()].dnsServers), createObject('value', createArray())), createObject('value', createArray()))]", - "networkSecurityGroupResourceId": "[if(contains(parameters('nicConfigurations')[copyIndex()], 'networkSecurityGroupResourceId'), createObject('value', parameters('nicConfigurations')[copyIndex()].networkSecurityGroupResourceId), createObject('value', ''))]", - "ipConfigurations": { - "value": "[parameters('nicConfigurations')[copyIndex()].ipConfigurations]" - }, - "lock": { - "value": "[coalesce(tryGet(parameters('nicConfigurations')[copyIndex()], 'lock'), parameters('lock'))]" - }, - "tags": { - "value": "[coalesce(tryGet(parameters('nicConfigurations')[copyIndex()], 'tags'), parameters('tags'))]" - }, - "diagnosticSettings": { - "value": "[tryGet(parameters('nicConfigurations')[copyIndex()], 'diagnosticSettings')]" - }, - "roleAssignments": { - "value": "[tryGet(parameters('nicConfigurations')[copyIndex()], 'roleAssignments')]" - }, - "enableTelemetry": { - "value": "[coalesce(tryGet(parameters('nicConfigurations')[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "18013796946460477676" - } - }, - "definitions": { - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to \u0007llLogs to collect all logs." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to AllMetrics to collect all metrics." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "metadata": { - "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - } - }, - "parameters": { - "networkInterfaceName": { - "type": "string" - }, - "virtualMachineName": { - "type": "string" - }, - "location": { - "type": "string" - }, - "tags": { - "type": "object", - "nullable": true - }, - "enableIPForwarding": { - "type": "bool", - "defaultValue": false - }, - "enableAcceleratedNetworking": { - "type": "bool", - "defaultValue": false - }, - "dnsServers": { - "type": "array", - "defaultValue": [] - }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable telemetry via a Globally Unique Identifier (GUID)." - } - }, - "networkSecurityGroupResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. The network security group (NSG) to attach to the network interface." - } - }, - "ipConfigurations": { - "type": "array" - }, - "lock": { - "$ref": "#/definitions/lockType" - }, - "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", - "metadata": { - "description": "Optional. The diagnostic settings of the Network Interface." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - } - }, - "resources": { - "networkInterface_publicIPAddresses": { - "copy": { - "name": "networkInterface_publicIPAddresses", - "count": "[length(parameters('ipConfigurations'))]" - }, - "condition": "[contains(parameters('ipConfigurations')[copyIndex()], 'pipconfiguration')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-publicIP-{1}', deployment().name, copyIndex())]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurations')[copyIndex()].pipconfiguration.publicIpNameSuffix)]" - }, - "diagnosticSettings": { - "value": "[tryGet(parameters('ipConfigurations')[copyIndex()], 'diagnosticSettings')]" - }, - "location": { - "value": "[parameters('location')]" - }, - "lock": { - "value": "[parameters('lock')]" - }, - "publicIPAddressVersion": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'publicIPAddressVersion'), createObject('value', parameters('ipConfigurations')[copyIndex()].publicIPAddressVersion), createObject('value', 'IPv4'))]", - "publicIPAllocationMethod": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'publicIPAllocationMethod'), createObject('value', parameters('ipConfigurations')[copyIndex()].publicIPAllocationMethod), createObject('value', 'Static'))]", - "publicIpPrefixResourceId": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'publicIPPrefixResourceId'), createObject('value', parameters('ipConfigurations')[copyIndex()].publicIPPrefixResourceId), createObject('value', ''))]", - "roleAssignments": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'roleAssignments'), createObject('value', parameters('ipConfigurations')[copyIndex()].roleAssignments), createObject('value', createArray()))]", - "skuName": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'skuName'), createObject('value', parameters('ipConfigurations')[copyIndex()].skuName), createObject('value', 'Standard'))]", - "skuTier": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'skuTier'), createObject('value', parameters('ipConfigurations')[copyIndex()].skuTier), createObject('value', 'Regional'))]", - "tags": { - "value": "[coalesce(tryGet(parameters('ipConfigurations')[copyIndex()], 'tags'), parameters('tags'))]" - }, - "zones": "[if(contains(parameters('ipConfigurations')[copyIndex()], 'zones'), createObject('value', parameters('ipConfigurations')[copyIndex()].zones), createObject('value', createArray('1', '2', '3')))]", - "enableTelemetry": { - "value": "[parameters('enableTelemetry')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "3488076626994379707" - }, - "name": "Public IP Addresses", - "description": "This module deploys a Public IP Address.", - "owner": "Azure/module-maintainers" - }, - "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "dnsSettingsType": { - "type": "object", - "properties": { - "domainNameLabel": { - "type": "string", - "metadata": { - "description": "Required. The domain name label. The concatenation of the domain name label and the regionalized DNS zone make up the fully qualified domain name associated with the public IP address. If a domain name label is specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system." - } - }, - "domainNameLabelScope": { - "type": "string", - "allowedValues": [ - "", - "NoReuse", - "ResourceGroupReuse", - "SubscriptionReuse", - "TenantReuse" - ], - "metadata": { - "description": "Required. The domain name label scope. If a domain name label and a domain name label scope are specified, an A DNS record is created for the public IP in the Microsoft Azure DNS system with a hashed value includes in FQDN." - } - }, - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Fully Qualified Domain Name of the A DNS record associated with the public IP. This is the concatenation of the domainNameLabel and the regionalized DNS zone." - } - }, - "reverseFqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The reverse FQDN. A user-visible, fully qualified domain name that resolves to this public IP address. If the reverseFqdn is specified, then a PTR DNS record is created pointing from the IP address in the in-addr.arpa domain to the reverse FQDN." - } - } - } - }, - "ddosSettingsType": { - "type": "object", - "properties": { - "ddosProtectionPlan": { - "type": "object", - "properties": { - "id": { - "type": "string" - } - }, - "metadata": { - "description": "Required. The DDoS protection plan ID associated with the public IP address." - } - }, - "protectionMode": { - "type": "string", - "allowedValues": [ - "Enabled" - ], - "metadata": { - "description": "Required. The DDoS protection policy customizations." - } - } - } - }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "metadata": { - "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the Public IP Address." - } - }, - "publicIpPrefixResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the Public IP Prefix object. This is only needed if you want your Public IPs created in a PIP Prefix." - } - }, - "publicIPAllocationMethod": { - "type": "string", - "defaultValue": "Static", - "allowedValues": [ - "Dynamic", - "Static" - ], - "metadata": { - "description": "Optional. The public IP address allocation method." - } - }, - "zones": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. A list of availability zones denoting the IP allocated for the resource needs to come from." - } - }, - "publicIPAddressVersion": { - "type": "string", - "defaultValue": "IPv4", - "allowedValues": [ - "IPv4", - "IPv6" - ], - "metadata": { - "description": "Optional. IP address version." - } - }, - "dnsSettings": { - "$ref": "#/definitions/dnsSettingsType", - "nullable": true, - "metadata": { - "description": "Optional. The DNS settings of the public IP address." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. The lock settings of the service." - } - }, - "skuName": { - "type": "string", - "defaultValue": "Standard", - "allowedValues": [ - "Basic", - "Standard" - ], - "metadata": { - "description": "Optional. Name of a public IP address SKU." - } - }, - "skuTier": { - "type": "string", - "defaultValue": "Regional", - "allowedValues": [ - "Global", - "Regional" - ], - "metadata": { - "description": "Optional. Tier of a public IP address SKU." - } - }, - "ddosSettings": { - "$ref": "#/definitions/ddosSettingsType", - "nullable": true, - "metadata": { - "description": "Optional. The DDoS protection plan configuration associated with the public IP address." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "idleTimeoutInMinutes": { - "type": "int", - "defaultValue": 4, - "metadata": { - "description": "Optional. The idle timeout of the public IP address." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - }, - "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", - "metadata": { - "description": "Optional. The diagnostic settings of the service." - } - } - }, - "variables": { - "builtInRoleNames": { - "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", - "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", - "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", - "Domain Services Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'eeaeda52-9324-47f6-8069-5d5bade478b2')]", - "Domain Services Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '361898ef-9ed1-48c2-849c-a832951106bb')]", - "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", - "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", - "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", - "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" - } - }, - "resources": { - "avmTelemetry": { - "condition": "[parameters('enableTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-publicipaddress.{0}.{1}', replace('0.2.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [], - "outputs": { - "telemetry": { - "type": "String", - "value": "For more information, see https://aka.ms/avm/TelemetryInfo" - } - } - } - } - }, - "publicIpAddress": { - "type": "Microsoft.Network/publicIPAddresses", - "apiVersion": "2023-04-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "sku": { - "name": "[parameters('skuName')]", - "tier": "[parameters('skuTier')]" - }, - "zones": "[parameters('zones')]", - "properties": { - "ddosSettings": "[parameters('ddosSettings')]", - "dnsSettings": "[parameters('dnsSettings')]", - "publicIPAddressVersion": "[parameters('publicIPAddressVersion')]", - "publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]", - "publicIPPrefix": "[if(not(empty(parameters('publicIpPrefixResourceId'))), createObject('id', parameters('publicIpPrefixResourceId')), null())]", - "idleTimeoutInMinutes": "[parameters('idleTimeoutInMinutes')]", - "ipTags": [] - } - }, - "publicIpAddress_lock": { - "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", - "type": "Microsoft.Authorization/locks", - "apiVersion": "2020-05-01", - "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", - "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", - "properties": { - "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", - "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" - }, - "dependsOn": [ - "publicIpAddress" - ] - }, - "publicIpAddress_roleAssignments": { - "copy": { - "name": "publicIpAddress_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" - }, - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/publicIPAddresses', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", - "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" - }, - "dependsOn": [ - "publicIpAddress" - ] - }, - "publicIpAddress_diagnosticSettings": { - "copy": { - "name": "publicIpAddress_diagnosticSettings", - "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" - }, - "type": "Microsoft.Insights/diagnosticSettings", - "apiVersion": "2021-05-01-preview", - "scope": "[format('Microsoft.Network/publicIPAddresses/{0}', parameters('name'))]", - "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", - "properties": { - "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", - "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", - "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", - "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", - "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", - "logs": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs', 'enabled', true())))]", - "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", - "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" - }, - "dependsOn": [ - "publicIpAddress" - ] - } - }, - "outputs": { - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group the public IP address was deployed into." - }, - "value": "[resourceGroup().name]" - }, - "name": { - "type": "string", - "metadata": { - "description": "The name of the public IP address." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the public IP address." - }, - "value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('name'))]" - }, - "ipAddress": { - "type": "string", - "metadata": { - "description": "The public IP address of the public IP address resource." - }, - "value": "[if(contains(reference('publicIpAddress'), 'ipAddress'), reference('publicIpAddress').ipAddress, '')]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('publicIpAddress', '2023-04-01', 'full').location]" - } - } - } - } - }, - "networkInterface": { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-NetworkInterface', deployment().name)]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[parameters('networkInterfaceName')]" - }, - "ipConfigurations": { - "copy": [ - { - "name": "value", - "count": "[length(parameters('ipConfigurations'))]", - "input": "[createObject('name', if(not(empty(parameters('ipConfigurations')[copyIndex('value')].name)), parameters('ipConfigurations')[copyIndex('value')].name, null()), 'primary', equals(copyIndex('value'), 0), 'privateIPAllocationMethod', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurations')[copyIndex('value')].privateIPAllocationMethod)), parameters('ipConfigurations')[copyIndex('value')].privateIPAllocationMethod, null()), null()), 'privateIPAddress', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'privateIPAddress'), if(not(empty(parameters('ipConfigurations')[copyIndex('value')].privateIPAddress)), parameters('ipConfigurations')[copyIndex('value')].privateIPAddress, null()), null()), 'publicIPAddressResourceId', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'pipconfiguration'), resourceId('Microsoft.Network/publicIPAddresses', format('{0}{1}', parameters('virtualMachineName'), parameters('ipConfigurations')[copyIndex('value')].pipconfiguration.publicIpNameSuffix)), null()), 'subnetResourceId', parameters('ipConfigurations')[copyIndex('value')].subnetResourceId, 'loadBalancerBackendAddressPools', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'loadBalancerBackendAddressPools'), parameters('ipConfigurations')[copyIndex('value')].loadBalancerBackendAddressPools, null()), 'applicationSecurityGroups', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'applicationSecurityGroups'), parameters('ipConfigurations')[copyIndex('value')].applicationSecurityGroups, null()), 'applicationGatewayBackendAddressPools', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'applicationGatewayBackendAddressPools'), parameters('ipConfigurations')[copyIndex('value')].applicationGatewayBackendAddressPools, null()), 'gatewayLoadBalancer', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'gatewayLoadBalancer'), parameters('ipConfigurations')[copyIndex('value')].gatewayLoadBalancer, null()), 'loadBalancerInboundNatRules', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'loadBalancerInboundNatRules'), parameters('ipConfigurations')[copyIndex('value')].loadBalancerInboundNatRules, null()), 'privateIPAddressVersion', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'privateIPAddressVersion'), parameters('ipConfigurations')[copyIndex('value')].privateIPAddressVersion, null()), 'virtualNetworkTaps', if(contains(parameters('ipConfigurations')[copyIndex('value')], 'virtualNetworkTaps'), parameters('ipConfigurations')[copyIndex('value')].virtualNetworkTaps, null()))]" - } - ] - }, - "location": { - "value": "[parameters('location')]" - }, - "tags": { - "value": "[parameters('tags')]" - }, - "diagnosticSettings": { - "value": "[parameters('diagnosticSettings')]" - }, - "dnsServers": "[if(not(empty(parameters('dnsServers'))), createObject('value', parameters('dnsServers')), createObject('value', createArray()))]", - "enableAcceleratedNetworking": { - "value": "[parameters('enableAcceleratedNetworking')]" - }, - "enableTelemetry": { - "value": "[parameters('enableTelemetry')]" - }, - "enableIPForwarding": { - "value": "[parameters('enableIPForwarding')]" - }, - "lock": { - "value": "[parameters('lock')]" - }, - "networkSecurityGroupResourceId": "[if(not(empty(parameters('networkSecurityGroupResourceId'))), createObject('value', parameters('networkSecurityGroupResourceId')), createObject('value', ''))]", - "roleAssignments": "[if(not(empty(parameters('roleAssignments'))), createObject('value', parameters('roleAssignments')), createObject('value', createArray()))]" - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "14617314094453038306" - }, - "name": "Network Interface", - "description": "This module deploys a Network Interface.", - "owner": "Azure/module-maintainers" - }, - "definitions": { - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } - }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to '' to disable log collection." - } - }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." - } - }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "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." - } - }, - "eventHubName": { - "type": "string", - "nullable": true, - "metadata": { - "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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } - }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"" - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "lockType": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify the name of lock." - } - }, - "kind": { - "type": "string", - "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" - ], - "nullable": true, - "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the network interface." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Resource tags." - } - }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "enableIPForwarding": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether IP forwarding is enabled on this network interface." - } - }, - "enableAcceleratedNetworking": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. If the network interface is accelerated networking enabled." - } - }, - "dnsServers": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. List of DNS servers IP addresses. Use 'AzureProvidedDNS' to switch to azure provided DNS resolution. 'AzureProvidedDNS' value cannot be combined with other IPs, it must be the only value in dnsServers collection." - } - }, - "networkSecurityGroupResourceId": { - "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. The network security group (NSG) to attach to the network interface." - } - }, - "auxiliaryMode": { - "type": "string", - "defaultValue": "None", - "allowedValues": [ - "Floating", - "MaxConnections", - "None" - ], - "metadata": { - "description": "Optional. Auxiliary mode of Network Interface resource. Not all regions are enabled for Auxiliary Mode Nic." - } - }, - "auxiliarySku": { - "type": "string", - "defaultValue": "None", - "allowedValues": [ - "A1", - "A2", - "A4", - "A8", - "None" - ], - "metadata": { - "description": "Optional. Auxiliary sku of Network Interface resource. Not all regions are enabled for Auxiliary Mode Nic." - } - }, - "disableTcpStateTracking": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether to disable tcp state tracking. Subscription must be registered for the Microsoft.Network/AllowDisableTcpStateTracking feature before this property can be set to true." - } - }, - "ipConfigurations": { - "type": "array", - "metadata": { - "description": "Required. A list of IPConfigurations of the network interface." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. The lock settings of the service." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." - } - }, - "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", - "metadata": { - "description": "Optional. The diagnostic settings of the service." - } - } - }, - "variables": { - "builtInRoleNames": { - "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", - "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", - "DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'befefa01-2a29-4197-83a8-272ff33ce314')]", - "Network Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4d97b98b-1d4f-4787-a291-c67834d212e7')]", - "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", - "Private DNS Zone Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b12aa53e-6015-4669-85d0-8515ebb3ae7f')]", - "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]" - } - }, - "resources": { - "avmTelemetry": { - "condition": "[parameters('enableTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-networkinterface.{0}.{1}', replace('0.2.2', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", - "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [], - "outputs": { - "telemetry": { - "type": "String", - "value": "For more information, see https://aka.ms/avm/TelemetryInfo" - } - } - } - } - }, - "networkInterface": { - "type": "Microsoft.Network/networkInterfaces", - "apiVersion": "2023-04-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "copy": [ - { - "name": "ipConfigurations", - "count": "[length(parameters('ipConfigurations'))]", - "input": { - "name": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'name'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].name, format('ipconfig0{0}', add(copyIndex('ipConfigurations'), 1)))]", - "properties": { - "primary": "[if(equals(copyIndex('ipConfigurations'), 0), true(), false())]", - "privateIPAllocationMethod": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'privateIPAllocationMethod'), if(not(empty(parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAllocationMethod)), parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAllocationMethod, null()), null())]", - "privateIPAddress": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'privateIPAddress'), if(not(empty(parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAddress)), parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAddress, null()), null())]", - "publicIPAddress": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'publicIPAddressResourceId'), if(not(equals(parameters('ipConfigurations')[copyIndex('ipConfigurations')].publicIPAddressResourceId, null())), createObject('id', parameters('ipConfigurations')[copyIndex('ipConfigurations')].publicIPAddressResourceId), null()), null())]", - "subnet": { - "id": "[parameters('ipConfigurations')[copyIndex('ipConfigurations')].subnetResourceId]" - }, - "loadBalancerBackendAddressPools": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'loadBalancerBackendAddressPools'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].loadBalancerBackendAddressPools, null())]", - "applicationSecurityGroups": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'applicationSecurityGroups'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].applicationSecurityGroups, null())]", - "applicationGatewayBackendAddressPools": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'applicationGatewayBackendAddressPools'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].applicationGatewayBackendAddressPools, null())]", - "gatewayLoadBalancer": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'gatewayLoadBalancer'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].gatewayLoadBalancer, null())]", - "loadBalancerInboundNatRules": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'loadBalancerInboundNatRules'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].loadBalancerInboundNatRules, null())]", - "privateIPAddressVersion": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'privateIPAddressVersion'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].privateIPAddressVersion, null())]", - "virtualNetworkTaps": "[if(contains(parameters('ipConfigurations')[copyIndex('ipConfigurations')], 'virtualNetworkTaps'), parameters('ipConfigurations')[copyIndex('ipConfigurations')].virtualNetworkTaps, null())]" - } - } - } - ], - "auxiliaryMode": "[parameters('auxiliaryMode')]", - "auxiliarySku": "[parameters('auxiliarySku')]", - "disableTcpStateTracking": "[parameters('disableTcpStateTracking')]", - "dnsSettings": "[if(not(empty(parameters('dnsServers'))), createObject('dnsServers', parameters('dnsServers')), null())]", - "enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]", - "enableIPForwarding": "[parameters('enableIPForwarding')]", - "networkSecurityGroup": "[if(not(empty(parameters('networkSecurityGroupResourceId'))), createObject('id', parameters('networkSecurityGroupResourceId')), null())]" - } - }, - "networkInterface_lock": { - "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", - "type": "Microsoft.Authorization/locks", - "apiVersion": "2020-05-01", - "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('name'))]", - "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", - "properties": { - "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", - "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" - }, - "dependsOn": [ - "networkInterface" - ] - }, - "networkInterface_diagnosticSettings": { - "copy": { - "name": "networkInterface_diagnosticSettings", - "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" - }, - "type": "Microsoft.Insights/diagnosticSettings", - "apiVersion": "2021-05-01-preview", - "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('name'))]", - "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", - "properties": { - "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", - "workspaceId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId')]", - "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", - "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", - "metrics": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics', 'timeGrain', null(), 'enabled', true())))]", - "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", - "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" - }, - "dependsOn": [ - "networkInterface" - ] - }, - "networkInterface_roleAssignments": { - "copy": { - "name": "networkInterface_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" - }, - "type": "Microsoft.Authorization/roleAssignments", - "apiVersion": "2022-04-01", - "scope": "[format('Microsoft.Network/networkInterfaces/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/networkInterfaces', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", - "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" - }, - "dependsOn": [ - "networkInterface" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the deployed resource." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the deployed resource." - }, - "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group of the deployed resource." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('networkInterface', '2023-04-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "networkInterface_publicIPAddresses" - ] - } - } - } - } - }, - "vm_aadJoinExtension": { - "condition": "[parameters('extensionAadJoinConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-AADLogin', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "AADLogin" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Azure.ActiveDirectory" - }, - "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AADLoginForWindows'), createObject('value', 'AADSSHLoginforLinux'))]", - "typeHandlerVersion": "[if(contains(parameters('extensionAadJoinConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAadJoinConfig').typeHandlerVersion), createObject('value', '1.0'))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAadJoinConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAadJoinConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionAadJoinConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAadJoinConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "settings": "[if(contains(parameters('extensionAadJoinConfig'), 'settings'), createObject('value', parameters('extensionAadJoinConfig').settings), createObject('value', createObject()))]", - "tags": { - "value": "[coalesce(tryGet(parameters('extensionAadJoinConfig'), 'tags'), parameters('tags'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_domainJoinExtension": { - "condition": "[parameters('extensionDomainJoinConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-DomainJoin', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "DomainJoin" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Compute" - }, - "type": { - "value": "JsonADDomainExtension" - }, - "typeHandlerVersion": "[if(contains(parameters('extensionDomainJoinConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDomainJoinConfig').typeHandlerVersion), createObject('value', '1.3'))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDomainJoinConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDomainJoinConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionDomainJoinConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDomainJoinConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "settings": { - "value": "[parameters('extensionDomainJoinConfig').settings]" - }, - "tags": { - "value": "[coalesce(tryGet(parameters('extensionDomainJoinConfig'), 'tags'), parameters('tags'))]" - }, - "protectedSettings": { - "value": { - "Password": "[parameters('extensionDomainJoinPassword')]" - } - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_microsoftAntiMalwareExtension": { - "condition": "[parameters('extensionAntiMalwareConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-MicrosoftAntiMalware', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "MicrosoftAntiMalware" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Azure.Security" - }, - "type": { - "value": "IaaSAntimalware" - }, - "typeHandlerVersion": "[if(contains(parameters('extensionAntiMalwareConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAntiMalwareConfig').typeHandlerVersion), createObject('value', '1.3'))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAntiMalwareConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAntiMalwareConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionAntiMalwareConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAntiMalwareConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "settings": { - "value": "[parameters('extensionAntiMalwareConfig').settings]" - }, - "tags": { - "value": "[coalesce(tryGet(parameters('extensionAntiMalwareConfig'), 'tags'), parameters('tags'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_azureMonitoringAgentExtension": { - "condition": "[parameters('extensionMonitoringAgentConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-AzureMonitoringAgent', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "AzureMonitoringAgent" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Azure.Monitor" - }, - "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AzureMonitorWindowsAgent'), createObject('value', 'AzureMonitorLinuxAgent'))]", - "typeHandlerVersion": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionMonitoringAgentConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '1.0'), createObject('value', '1.21')))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionMonitoringAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionMonitoringAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionMonitoringAgentConfig').enableAutomaticUpgrade), createObject('value', true()))]", - "tags": { - "value": "[coalesce(tryGet(parameters('extensionMonitoringAgentConfig'), 'tags'), parameters('tags'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_dependencyAgentExtension": { - "condition": "[parameters('extensionDependencyAgentConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-DependencyAgent', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "DependencyAgent" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Azure.Monitoring.DependencyAgent" - }, - "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'DependencyAgentWindows'), createObject('value', 'DependencyAgentLinux'))]", - "typeHandlerVersion": "[if(contains(parameters('extensionDependencyAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDependencyAgentConfig').typeHandlerVersion), createObject('value', '9.5'))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDependencyAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDependencyAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionDependencyAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDependencyAgentConfig').enableAutomaticUpgrade), createObject('value', true()))]", - "tags": { - "value": "[coalesce(tryGet(parameters('extensionDependencyAgentConfig'), 'tags'), parameters('tags'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_networkWatcherAgentExtension": { - "condition": "[parameters('extensionNetworkWatcherAgentConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-NetworkWatcherAgent', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "NetworkWatcherAgent" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Azure.NetworkWatcher" - }, - "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'NetworkWatcherAgentWindows'), createObject('value', 'NetworkWatcherAgentLinux'))]", - "typeHandlerVersion": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').typeHandlerVersion), createObject('value', '1.4'))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionNetworkWatcherAgentConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionNetworkWatcherAgentConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "tags": { - "value": "[coalesce(tryGet(parameters('extensionNetworkWatcherAgentConfig'), 'tags'), parameters('tags'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_desiredStateConfigurationExtension": { - "condition": "[parameters('extensionDSCConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-DesiredStateConfiguration', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "DesiredStateConfiguration" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Powershell" - }, - "type": { - "value": "DSC" - }, - "typeHandlerVersion": "[if(contains(parameters('extensionDSCConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionDSCConfig').typeHandlerVersion), createObject('value', '2.77'))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionDSCConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionDSCConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionDSCConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionDSCConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "settings": "[if(contains(parameters('extensionDSCConfig'), 'settings'), createObject('value', parameters('extensionDSCConfig').settings), createObject('value', createObject()))]", - "tags": { - "value": "[coalesce(tryGet(parameters('extensionDSCConfig'), 'tags'), parameters('tags'))]" - }, - "protectedSettings": "[if(contains(parameters('extensionDSCConfig'), 'protectedSettings'), createObject('value', parameters('extensionDSCConfig').protectedSettings), createObject('value', createObject()))]" - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm" - ] - }, - "vm_customScriptExtension": { - "condition": "[parameters('extensionCustomScriptConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-CustomScriptExtension', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "CustomScriptExtension" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'Microsoft.Compute'), createObject('value', 'Microsoft.Azure.Extensions'))]", - "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'CustomScriptExtension'), createObject('value', 'CustomScript'))]", - "typeHandlerVersion": "[if(contains(parameters('extensionCustomScriptConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionCustomScriptConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '1.10'), createObject('value', '2.1')))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionCustomScriptConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionCustomScriptConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionCustomScriptConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionCustomScriptConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "settings": { - "value": { - "copy": [ - { - "name": "fileUris", - "count": "[length(parameters('extensionCustomScriptConfig').fileData)]", - "input": "[if(contains(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')], 'storageAccountId'), format('{0}?{1}', parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri, listAccountSas(parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].storageAccountId, '2019-04-01', variables('accountSasProperties')).accountSasToken), parameters('extensionCustomScriptConfig').fileData[copyIndex('fileUris')].uri)]" - } - ] - } - }, - "tags": { - "value": "[coalesce(tryGet(parameters('extensionCustomScriptConfig'), 'tags'), parameters('tags'))]" - }, - "protectedSettings": { - "value": "[parameters('extensionCustomScriptProtectedSetting')]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm", - "vm_desiredStateConfigurationExtension" - ] - }, - "vm_azureDiskEncryptionExtension": { - "condition": "[parameters('extensionAzureDiskEncryptionConfig').enabled]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-AzureDiskEncryption', uniqueString(deployment().name, parameters('location')))]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "virtualMachineName": { - "value": "[parameters('name')]" - }, - "name": { - "value": "AzureDiskEncryption" - }, - "location": { - "value": "[parameters('location')]" - }, - "publisher": { - "value": "Microsoft.Azure.Security" - }, - "type": "[if(equals(parameters('osType'), 'Windows'), createObject('value', 'AzureDiskEncryption'), createObject('value', 'AzureDiskEncryptionForLinux'))]", - "typeHandlerVersion": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'typeHandlerVersion'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').typeHandlerVersion), if(equals(parameters('osType'), 'Windows'), createObject('value', '2.2'), createObject('value', '1.1')))]", - "autoUpgradeMinorVersion": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'autoUpgradeMinorVersion'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').autoUpgradeMinorVersion), createObject('value', true()))]", - "enableAutomaticUpgrade": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'enableAutomaticUpgrade'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').enableAutomaticUpgrade), createObject('value', false()))]", - "forceUpdateTag": "[if(contains(parameters('extensionAzureDiskEncryptionConfig'), 'forceUpdateTag'), createObject('value', parameters('extensionAzureDiskEncryptionConfig').forceUpdateTag), createObject('value', '1.0'))]", - "settings": { - "value": "[parameters('extensionAzureDiskEncryptionConfig').settings]" - }, - "tags": { - "value": "[coalesce(tryGet(parameters('extensionAzureDiskEncryptionConfig'), 'tags'), parameters('tags'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "13562327621635125722" - }, - "name": "Virtual Machine Extensions", - "description": "This module deploys a Virtual Machine Extension.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "virtualMachineName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent virtual machine that extension is provisioned for. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the virtual machine extension." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. The location the extension is deployed to." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the extension handler publisher." - } - }, - "type": { - "type": "string", - "metadata": { - "description": "Required. Specifies the type of the extension; an example is \"CustomScriptExtension\"." - } - }, - "typeHandlerVersion": { - "type": "string", - "metadata": { - "description": "Required. Specifies the version of the script handler." - } - }, - "autoUpgradeMinorVersion": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true." - } - }, - "forceUpdateTag": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. How the extension handler should be forced to update even if the extension configuration has not changed." - } - }, - "settings": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific settings." - } - }, - "protectedSettings": { - "type": "secureObject", - "nullable": true, - "metadata": { - "description": "Optional. Any object that contains the extension specific protected settings." - } - }, - "supressFailures": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Indicates whether failures stemming from the extension will be suppressed (Operational failures such as not connecting to the VM will not be suppressed regardless of this value). The default is false." - } - }, - "enableAutomaticUpgrade": { - "type": "bool", - "metadata": { - "description": "Required. Indicates whether the extension should be automatically upgraded by the platform if there is a newer version of the extension available." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags of the resource." - } - } - }, - "resources": { - "virtualMachine": { - "existing": true, - "type": "Microsoft.Compute/virtualMachines", - "apiVersion": "2022-11-01", - "name": "[parameters('virtualMachineName')]" - }, - "extension": { - "type": "Microsoft.Compute/virtualMachines/extensions", - "apiVersion": "2022-11-01", - "name": "[format('{0}/{1}', parameters('virtualMachineName'), parameters('name'))]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", - "properties": { - "publisher": "[parameters('publisher')]", - "type": "[parameters('type')]", - "typeHandlerVersion": "[parameters('typeHandlerVersion')]", - "autoUpgradeMinorVersion": "[parameters('autoUpgradeMinorVersion')]", - "enableAutomaticUpgrade": "[parameters('enableAutomaticUpgrade')]", - "forceUpdateTag": "[parameters('forceUpdateTag')]", - "settings": "[parameters('settings')]", - "protectedSettings": "[parameters('protectedSettings')]", - "suppressFailures": "[parameters('supressFailures')]" - }, - "dependsOn": [ - "virtualMachine" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the extension." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the extension." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('virtualMachineName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the extension was created in." - }, - "value": "[resourceGroup().name]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('extension', '2022-11-01', 'full').location]" - } - } - } - }, - "dependsOn": [ - "vm", - "vm_azureMonitoringAgentExtension", - "vm_customScriptExtension" - ] - }, - "vm_backup": { - "condition": "[not(empty(parameters('backupVaultName')))]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-VM-Backup', uniqueString(deployment().name, parameters('location')))]", - "resourceGroup": "[parameters('backupVaultResourceGroup')]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "name": { - "value": "[format('vm;iaasvmcontainerv2;{0};{1}', resourceGroup().name, parameters('name'))]" - }, - "location": { - "value": "[parameters('location')]" - }, - "policyId": { - "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupPolicies', parameters('backupVaultName'), parameters('backupPolicyName'))]" - }, - "protectedItemType": { - "value": "Microsoft.Compute/virtualMachines" - }, - "protectionContainerName": { - "value": "[format('iaasvmcontainer;iaasvmcontainerv2;{0};{1}', resourceGroup().name, parameters('name'))]" - }, - "recoveryVaultName": { - "value": "[parameters('backupVaultName')]" - }, - "sourceResourceId": { - "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "12595215410082531283" - }, - "name": "Recovery Service Vaults Protection Container Protected Item", - "description": "This module deploys a Recovery Services Vault Protection Container Protected Item.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the resource." - } - }, - "protectionContainerName": { - "type": "string", - "metadata": { - "description": "Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment." - } - }, - "recoveryVaultName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "protectedItemType": { - "type": "string", - "allowedValues": [ - "AzureFileShareProtectedItem", - "AzureVmWorkloadSAPAseDatabase", - "AzureVmWorkloadSAPHanaDatabase", - "AzureVmWorkloadSQLDatabase", - "DPMProtectedItem", - "GenericProtectedItem", - "MabFileFolderProtectedItem", - "Microsoft.ClassicCompute/virtualMachines", - "Microsoft.Compute/virtualMachines", - "Microsoft.Sql/servers/databases" - ], - "metadata": { - "description": "Required. The backup item type." - } - }, - "policyId": { - "type": "string", - "metadata": { - "description": "Required. ID of the backup policy with which this item is backed up." - } - }, - "sourceResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the resource to back up." - } - } - }, - "resources": [ - { - "type": "Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems", - "apiVersion": "2023-01-01", - "name": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]", - "location": "[parameters('location')]", - "properties": { - "protectedItemType": "[parameters('protectedItemType')]", - "policyId": "[parameters('policyId')]", - "sourceResourceId": "[parameters('sourceResourceId')]" - } - } - ], - "outputs": { - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the Resource Group the protected item was created in." - }, - "value": "[resourceGroup().name]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the protected item." - }, - "value": "[resourceId('Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems', split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[0], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[1], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[2], split(format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name')), '/')[3])]" - }, - "name": { - "type": "string", - "metadata": { - "description": "The Name of the protected item." - }, - "value": "[format('{0}/Azure/{1}/{2}', parameters('recoveryVaultName'), parameters('protectionContainerName'), parameters('name'))]" - } - } - } - }, - "dependsOn": [ - "vm", - "vm_aadJoinExtension", - "vm_azureMonitoringAgentExtension", - "vm_customScriptExtension", - "vm_dependencyAgentExtension", - "vm_desiredStateConfigurationExtension", - "vm_domainJoinExtension", - "vm_microsoftAntiMalwareExtension", - "vm_networkWatcherAgentExtension" - ] - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the VM." - }, - "value": "[parameters('name')]" - }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the VM." - }, - "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The name of the resource group the VM was created in." - }, - "value": "[resourceGroup().name]" - }, - "systemAssignedMIPrincipalId": { - "type": "string", - "metadata": { - "description": "The principal ID of the system assigned identity." - }, - "value": "[if(and(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), contains(reference('vm', '2022-11-01', 'full').identity, 'principalId')), reference('vm', '2022-11-01', 'full').identity.principalId, '')]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('vm', '2022-11-01', 'full').location]" - } - } -} \ No newline at end of file diff --git a/avm/res/compute/virtual-machine/modules/nic-configuration.bicep b/avm/res/compute/virtual-machine/modules/nic-configuration.bicep deleted file mode 100644 index 770d924a7d..0000000000 --- a/avm/res/compute/virtual-machine/modules/nic-configuration.bicep +++ /dev/null @@ -1,153 +0,0 @@ -param networkInterfaceName string -param virtualMachineName string -param location string -param tags object? -param enableIPForwarding bool = false -param enableAcceleratedNetworking bool = false -param dnsServers array = [] - -@description('Required. Enable telemetry via a Globally Unique Identifier (GUID).') -param enableTelemetry bool - -@description('Optional. The network security group (NSG) to attach to the network interface.') -param networkSecurityGroupResourceId string = '' - -param ipConfigurations array -param lock lockType - -@description('Optional. The diagnostic settings of the Network Interface.') -param diagnosticSettings diagnosticSettingType - -@description('Optional. Array of role assignments to create.') -param roleAssignments roleAssignmentType - -module networkInterface_publicIPAddresses 'br/public:avm/res/network/public-ip-address:0.2.1' = [for (ipConfiguration, index) in ipConfigurations: if (contains(ipConfiguration, 'pipconfiguration')) { - name: '${deployment().name}-publicIP-${index}' - params: { - name: '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}' - diagnosticSettings: ipConfiguration.?diagnosticSettings - location: location - lock: lock - publicIPAddressVersion: contains(ipConfiguration, 'publicIPAddressVersion') ? ipConfiguration.publicIPAddressVersion : 'IPv4' - publicIPAllocationMethod: contains(ipConfiguration, 'publicIPAllocationMethod') ? ipConfiguration.publicIPAllocationMethod : 'Static' - publicIpPrefixResourceId: contains(ipConfiguration, 'publicIPPrefixResourceId') ? ipConfiguration.publicIPPrefixResourceId : '' - roleAssignments: contains(ipConfiguration, 'roleAssignments') ? ipConfiguration.roleAssignments : [] - skuName: contains(ipConfiguration, 'skuName') ? ipConfiguration.skuName : 'Standard' - skuTier: contains(ipConfiguration, 'skuTier') ? ipConfiguration.skuTier : 'Regional' - tags: ipConfiguration.?tags ?? tags - zones: contains(ipConfiguration, 'zones') ? ipConfiguration.zones : [ - '1' - '2' - '3' - ] - enableTelemetry: enableTelemetry - } -}] - -module networkInterface 'br/public:avm/res/network/network-interface:0.2.2' = { - name: '${deployment().name}-NetworkInterface' - params: { - name: networkInterfaceName - ipConfigurations: [for (ipConfiguration, index) in ipConfigurations: { - name: !empty(ipConfiguration.name) ? ipConfiguration.name : null - primary: index == 0 - privateIPAllocationMethod: contains(ipConfiguration, 'privateIPAllocationMethod') ? (!empty(ipConfiguration.privateIPAllocationMethod) ? ipConfiguration.privateIPAllocationMethod : null) : null - privateIPAddress: contains(ipConfiguration, 'privateIPAddress') ? (!empty(ipConfiguration.privateIPAddress) ? ipConfiguration.privateIPAddress : null) : null - publicIPAddressResourceId: contains(ipConfiguration, 'pipconfiguration') ? resourceId('Microsoft.Network/publicIPAddresses', '${virtualMachineName}${ipConfiguration.pipconfiguration.publicIpNameSuffix}') : null - subnetResourceId: ipConfiguration.subnetResourceId - loadBalancerBackendAddressPools: contains(ipConfiguration, 'loadBalancerBackendAddressPools') ? ipConfiguration.loadBalancerBackendAddressPools : null - applicationSecurityGroups: contains(ipConfiguration, 'applicationSecurityGroups') ? ipConfiguration.applicationSecurityGroups : null - applicationGatewayBackendAddressPools: contains(ipConfiguration, 'applicationGatewayBackendAddressPools') ? ipConfiguration.applicationGatewayBackendAddressPools : null - gatewayLoadBalancer: contains(ipConfiguration, 'gatewayLoadBalancer') ? ipConfiguration.gatewayLoadBalancer : null - loadBalancerInboundNatRules: contains(ipConfiguration, 'loadBalancerInboundNatRules') ? ipConfiguration.loadBalancerInboundNatRules : null - privateIPAddressVersion: contains(ipConfiguration, 'privateIPAddressVersion') ? ipConfiguration.privateIPAddressVersion : null - virtualNetworkTaps: contains(ipConfiguration, 'virtualNetworkTaps') ? ipConfiguration.virtualNetworkTaps : null - }] - location: location - tags: tags - diagnosticSettings: diagnosticSettings - dnsServers: !empty(dnsServers) ? dnsServers : [] - enableAcceleratedNetworking: enableAcceleratedNetworking - enableTelemetry: enableTelemetry - enableIPForwarding: enableIPForwarding - lock: lock - networkSecurityGroupResourceId: !empty(networkSecurityGroupResourceId) ? networkSecurityGroupResourceId : '' - roleAssignments: !empty(roleAssignments) ? roleAssignments : [] - } - dependsOn: [ - networkInterface_publicIPAddresses - ] -} - -// =============== // -// Definitions // -// =============== // - -type lockType = { - @description('Optional. Specify the name of lock.') - name: string? - - @description('Optional. Specify the type of lock.') - kind: ('CanNotDelete' | 'ReadOnly' | 'None')? -}? - -type diagnosticSettingType = { - @description('Optional. The name of diagnostic setting.') - name: string? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') - logCategoriesAndGroups: { - @description('Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here.') - category: string? - - @description('Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to llLogs to collect all logs.') - categoryGroup: string? - }[]? - - @description('Optional. The name of logs that will be streamed. "allLogs" includes all possible logs for the resource. Set to \'\' to disable log collection.') - metricCategories: { - @description('Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to AllMetrics to collect all metrics.') - category: string - }[]? - - @description('Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type.') - logAnalyticsDestinationType: ('Dedicated' | 'AzureDiagnostics')? - - @description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') - workspaceResourceId: string? - - @description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') - storageAccountResourceId: 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.') - eventHubAuthorizationRuleResourceId: 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. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') - eventHubName: string? - - @description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.') - marketplacePartnerResourceId: string? -}[]? - -type roleAssignmentType = { - @description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') - roleDefinitionIdOrName: string - - @description('Required. The principal ID of the principal (user/group/identity) to assign the role to.') - principalId: string - - @description('Optional. The principal type of the assigned principal ID.') - principalType: ('ServicePrincipal' | 'Group' | 'User' | 'ForeignGroup' | 'Device')? - - @description('Optional. The description of the role assignment.') - description: string? - - @description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container".') - condition: string? - - @description('Optional. Version of the condition.') - conditionVersion: '2.0'? - - @description('Optional. The Resource Id of the delegated managed identity resource.') - delegatedManagedIdentityResourceId: string? -}[]? diff --git a/avm/res/compute/virtual-machine/modules/protected-item.bicep b/avm/res/compute/virtual-machine/modules/protected-item.bicep deleted file mode 100644 index dbba0616ac..0000000000 --- a/avm/res/compute/virtual-machine/modules/protected-item.bicep +++ /dev/null @@ -1,55 +0,0 @@ -metadata name = 'Recovery Service Vaults Protection Container Protected Item' -metadata description = 'This module deploys a Recovery Services Vault Protection Container Protected Item.' -metadata owner = 'Azure/module-maintainers' - -@description('Required. Name of the resource.') -param name string - -@description('Conditional. Name of the Azure Recovery Service Vault Protection Container. Required if the template is used in a standalone deployment.') -param protectionContainerName string - -@description('Conditional. The name of the parent Azure Recovery Service Vault. Required if the template is used in a standalone deployment.') -param recoveryVaultName string - -@description('Optional. Location for all resources.') -param location string = resourceGroup().location - -@allowed([ - 'AzureFileShareProtectedItem' - 'AzureVmWorkloadSAPAseDatabase' - 'AzureVmWorkloadSAPHanaDatabase' - 'AzureVmWorkloadSQLDatabase' - 'DPMProtectedItem' - 'GenericProtectedItem' - 'MabFileFolderProtectedItem' - 'Microsoft.ClassicCompute/virtualMachines' - 'Microsoft.Compute/virtualMachines' - 'Microsoft.Sql/servers/databases' -]) -@description('Required. The backup item type.') -param protectedItemType string - -@description('Required. ID of the backup policy with which this item is backed up.') -param policyId string - -@description('Required. Resource ID of the resource to back up.') -param sourceResourceId string - -resource protectedItem 'Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems@2023-01-01' = { - name: '${recoveryVaultName}/Azure/${protectionContainerName}/${name}' - location: location - properties: { - protectedItemType: any(protectedItemType) - policyId: policyId - sourceResourceId: sourceResourceId - } -} - -@description('The name of the Resource Group the protected item was created in.') -output resourceGroupName string = resourceGroup().name - -@description('The resource ID of the protected item.') -output resourceId string = protectedItem.id - -@description('The Name of the protected item.') -output name string = protectedItem.name diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep deleted file mode 100644 index fe37b069fa..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/dependencies.bicep +++ /dev/null @@ -1,86 +0,0 @@ -@description('Required. The name of the Virtual Network to create.') -param virtualNetworkName string - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -@description('Required. The name of the Deployment Script to create for the SSH Key generation.') -param sshDeploymentScriptName string - -@description('Required. The name of the SSH Key to create.') -param sshKeyName string - -@description('Optional. The location to deploy resources to.') -param location string = resourceGroup().location - -var addressPrefix = '10.0.0.0/16' - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) - scope: resourceGroup() - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor - principalType: 'ServicePrincipal' - } -} - -resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: sshDeploymentScriptName - location: location - kind: 'AzurePowerShell' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - azPowerShellVersion: '9.0' - retentionInterval: 'P1D' - arguments: ' -SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') - } - dependsOn: [ - msiRGContrRoleAssignment - ] -} - -resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { - name: sshKeyName - location: location - properties: { - publicKey: sshDeploymentScript.properties.outputs.publicKey - } -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The Public Key of the created SSH Key.') -output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep deleted file mode 100644 index b506288b88..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/linux.atmg/main.test.bicep +++ /dev/null @@ -1,123 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using automanage for the VM.' -metadata description = 'This instance deploys the module with registering to an automation account.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'cvmlinatmg' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - } -} - -// ============== // -// Test Execution // -// ============== // - -// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { -// name: sshKeyName -// scope: resourceGroup -// } - -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - name: '${namePrefix}${serviceShort}' - adminUsername: 'localAdminUser' - imageReference: { - publisher: 'Canonical' - offer: '0001-com-ubuntu-server-jammy' - sku: '22_04-lts-gen2' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - zones: [ - '1' - '2' - '3' - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - nicSuffix: '-nic-01' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - ] - osDisk: { - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - vmSize: 'Standard_DS2_v2' - configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' - disablePasswordAuthentication: true - publicKeys: [ - { - keyData: nestedDependencies.outputs.SSHKeyPublicKey - path: '/home/localAdminUser/.ssh/authorized_keys' - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - dependsOn: [ - nestedDependencies // Required to leverage `existing` SSH key reference - ] -}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep deleted file mode 100644 index 023a59cca3..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/dependencies.bicep +++ /dev/null @@ -1,86 +0,0 @@ -@description('Required. The name of the Virtual Network to create.') -param virtualNetworkName string - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -@description('Required. The name of the Deployment Script to create for the SSH Key generation.') -param sshDeploymentScriptName string - -@description('Required. The name of the SSH Key to create.') -param sshKeyName string - -@description('Optional. The location to deploy resources to.') -param location string = resourceGroup().location - -var addressPrefix = '10.0.0.0/16' - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) - scope: resourceGroup() - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor - principalType: 'ServicePrincipal' - } -} - -resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: sshDeploymentScriptName - location: location - kind: 'AzurePowerShell' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - azPowerShellVersion: '9.0' - retentionInterval: 'P1D' - arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/New-SSHKey.ps1') - } - dependsOn: [ - msiRGContrRoleAssignment - ] -} - -resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { - name: sshKeyName - location: location - properties: { - publicKey: sshDeploymentScript.properties.outputs.publicKey - } -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The Public Key of the created SSH Key.') -output SSHKeyPublicKey string = sshKey.properties.publicKey diff --git a/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep deleted file mode 100644 index ff60259195..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/linux.defaults/main.test.bicep +++ /dev/null @@ -1,103 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using only defaults' -metadata description = 'This instance deploys the module with the minimum set of required parameters.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'cvmlinmin' - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - sshDeploymentScriptName: 'dep-${namePrefix}-ds-${serviceShort}' - sshKeyName: 'dep-${namePrefix}-ssh-${serviceShort}' - } -} - -// ============== // -// Test Execution // -// ============== // - -// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { -// name: sshKeyName -// scope: resourceGroup -// } - -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - name: '${namePrefix}${serviceShort}' - adminUsername: 'localAdminUser' - imageReference: { - publisher: 'Canonical' - offer: '0001-com-ubuntu-server-jammy' - sku: '22_04-lts-gen2' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - } - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - diskSizeGB: '128' - caching: 'ReadWrite' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - vmSize: 'Standard_DS2_v2' - disablePasswordAuthentication: true - publicKeys: [ - { - keyData: nestedDependencies.outputs.SSHKeyPublicKey - path: '/home/localAdminUser/.ssh/authorized_keys' - } - ] - } - dependsOn: [ - nestedDependencies // Required to leverage `existing` SSH key reference - ] -}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep deleted file mode 100644 index 4d6d69ed7a..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/dependencies.bicep +++ /dev/null @@ -1,267 +0,0 @@ -@description('Required. The name of the Virtual Network to create.') -param virtualNetworkName string - -@description('Required. The name of the Application Security Group to create.') -param applicationSecurityGroupName string - -@description('Required. The name of the Load Balancer to create.') -param loadBalancerName string - -@description('Required. The name of the Recovery Services Vault to create.') -param recoveryServicesVaultName string - -@description('Required. The name of the Key Vault to create.') -param keyVaultName string - -@description('Required. The name of the Storage Account to create.') -param storageAccountName string - -@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') -param storageUploadDeploymentScriptName string - -@description('Required. The name of the Proximity Placement Group to create.') -param proximityPlacementGroupName string - -@description('Optional. The location to deploy resources to.') -param location string = resourceGroup().location - -var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' -var addressPrefix = '10.0.0.0/16' - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-04-01' = { - name: applicationSecurityGroupName - location: location -} - -resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { - name: loadBalancerName - location: location - sku: { - name: 'Standard' - } - properties: { - frontendIPConfigurations: [ - { - name: 'privateIPConfig1' - properties: { - subnet: virtualNetwork.properties.subnets[0] - } - } - ] - backendAddressPools: [ - { - name: 'servers' - } - ] - } -} - -resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-04-01' = { - name: recoveryServicesVaultName - location: location - sku: { - name: 'RS0' - tier: 'Standard' - } - properties: {} - - resource backupPolicy 'backupPolicies@2022-03-01' = { - name: 'backupPolicy' - properties: { - backupManagementType: 'AzureIaasVM' - instantRPDetails: {} - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunFrequency: 'Daily' - scheduleRunTimes: [ - '2019-11-07T07:00:00Z' - ] - scheduleWeeklyFrequency: 0 - } - retentionPolicy: { - retentionPolicyType: 'LongTermRetentionPolicy' - dailySchedule: { - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 180 - durationType: 'Days' - } - } - weeklySchedule: { - daysOfTheWeek: [ - 'Sunday' - ] - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 12 - durationType: 'Weeks' - } - } - monthlySchedule: { - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' - ] - weeksOfTheMonth: [ - 'First' - ] - } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 60 - durationType: 'Months' - } - } - yearlySchedule: { - retentionScheduleFormatType: 'Weekly' - monthsOfYear: [ - 'January' - ] - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' - ] - weeksOfTheMonth: [ - 'First' - ] - } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 10 - durationType: 'Years' - } - } - } - instantRpRetentionRangeInDays: 2 - timeZone: 'UTC' - protectedItemsCount: 0 - } - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: null - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] - } - - resource key 'keys@2022-07-01' = { - name: 'encryptionKey' - properties: { - kty: 'RSA' - } - } -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - - resource blobService 'blobServices@2021-09-01' = { - name: 'default' - - resource container 'containers@2021-09-01' = { - name: 'scripts' - } - } -} - -resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: storageUploadDeploymentScriptName - location: location - kind: 'AzurePowerShell' - properties: { - azPowerShellVersion: '9.0' - retentionInterval: 'P1D' - arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') - } -} - -resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { - name: proximityPlacementGroupName - location: location -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The resource ID of the created Application Security Group.') -output applicationSecurityGroupResourceId string = applicationSecurityGroup.id - -@description('The resource ID of the created Load Balancer Backend Pool.') -output loadBalancerBackendPoolResourceId string = loadBalancer.properties.backendAddressPools[0].id - -@description('The name of the created Recovery Services Vault.') -output recoveryServicesVaultName string = recoveryServicesVault.name - -@description('The name of the Resource Group, the Recovery Services Vault was created in.') -output recoveryServicesVaultResourceGroupName string = resourceGroup().name - -@description('The name of the Backup Policy created in the Backup Recovery Vault.') -output recoveryServicesVaultBackupPolicyName string = recoveryServicesVault::backupPolicy.name - -@description('The resource ID of the created Key Vault.') -output keyVaultResourceId string = keyVault.id - -@description('The URL of the created Key Vault.') -output keyVaultUrl string = keyVault.properties.vaultUri - -@description('The URL of the created Key Vault Encryption Key.') -output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion - -@description('The resource ID of the created Storage Account.') -output storageAccountResourceId string = storageAccount.id - -@description('The name of the Custom Script Extension in the created Storage Account.') -output storageAccountCSEFileName string = storageAccountCSEFileName - -@description('The URL of the Custom Script Extension in the created Storage Account') -output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' - -@description('The resource ID of the created Proximity Placement Group.') -output proximityPlacementGroupResourceId string = proximityPlacementGroup.id diff --git a/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep deleted file mode 100644 index 21c55ad87c..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/waf-aligned/main.test.bicep +++ /dev/null @@ -1,293 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'WAF-aligned' -metadata description = 'This instance deploys the module in alignment with the best-practices of the Well-Architected Framework.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'cvmwinwaf' - -@description('Optional. The password to leverage for the login.') -@secure() -param password string = newGuid() - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - applicationSecurityGroupName: 'dep-${namePrefix}-asg-${serviceShort}' - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' - loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' - recoveryServicesVaultName: 'dep-${namePrefix}-rsv-${serviceShort}' - storageAccountName: 'dep${namePrefix}sa${serviceShort}01' - storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' - proximityPlacementGroupName: 'dep-${namePrefix}-ppg-${serviceShort}' - } -} - -// Diagnostics -// =========== -module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' - params: { - storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' - logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' - eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' - eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' - location: location - } -} - -// ============== // -// Test Execution // -// ============== // - -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - name: '${namePrefix}${serviceShort}' - computerName: '${namePrefix}winvm1' - adminUsername: 'VMAdmin' - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2019-datacenter' - version: 'latest' - } - nicConfigurations: [ - { - deleteOption: 'Delete' - ipConfigurations: [ - { - applicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - loadBalancerBackendAddressPools: [ - { - id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId - } - ] - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - } - zones: [ - '1' - '2' - '3' - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - } - ] - nicSuffix: '-nic-01' - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - } - ] - osDisk: { - caching: 'ReadWrite' - createOption: 'fromImage' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - adminPassword: password - availabilityZone: 2 - backupPolicyName: nestedDependencies.outputs.recoveryServicesVaultBackupPolicyName - backupVaultName: nestedDependencies.outputs.recoveryServicesVaultName - backupVaultResourceGroup: nestedDependencies.outputs.recoveryServicesVaultResourceGroupName - dataDisks: [ - { - caching: 'ReadOnly' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - { - caching: 'ReadOnly' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - ] - enableAutomaticUpdates: true - patchMode: 'AutomaticByPlatform' - encryptionAtHost: false - extensionAntiMalwareConfig: { - enabled: true - settings: { - AntimalwareEnabled: 'true' - Exclusions: { - Extensions: '.ext1;.ext2' - Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' - Processes: 'excludedproc1.exe;excludedproc2.exe' - } - RealtimeProtectionEnabled: 'true' - ScheduledScanSettings: { - day: '7' - isEnabled: 'true' - scanType: 'Quick' - time: '120' - } - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: nestedDependencies.outputs.storageAccountResourceId - uri: nestedDependencies.outputs.storageAccountCSEFileUrl - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionCustomScriptProtectedSetting: { - commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' - } - extensionDependencyAgentConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl - KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyVaultURL: nestedDependencies.outputs.keyVaultUrl - ResizeOSDisk: 'false' - VolumeType: 'All' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - } - extensionAadJoinConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionDSCConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionMonitoringAgentConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionNetworkWatcherAgentConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } -}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep deleted file mode 100644 index 68972ec7ec..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/dependencies.bicep +++ /dev/null @@ -1,30 +0,0 @@ -@description('Required. The name of the Virtual Network to create.') -param virtualNetworkName string - -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -var addressPrefix = '10.0.0.0/16' - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep deleted file mode 100644 index 4c9c55e6b3..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/windows.defaults/main.test.bicep +++ /dev/null @@ -1,86 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using only defaults' -metadata description = 'This instance deploys the module with the minimum set of required parameters.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'cvmwinmin' - -@description('Optional. The password to leverage for the login.') -@secure() -param password string = newGuid() - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - } -} - -// ============== // -// Test Execution // -// ============== // -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - name: '${namePrefix}${serviceShort}' - adminUsername: 'localAdminUser' - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2022-datacenter-azure-edition' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - diskSizeGB: '128' - caching: 'ReadWrite' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - adminPassword: password - } -}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep deleted file mode 100644 index e198bcd227..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/windows.max/dependencies.bicep +++ /dev/null @@ -1,310 +0,0 @@ -@description('Required. The name of the Virtual Network to create.') -param virtualNetworkName string - -@description('Required. The name of the Application Security Group to create.') -param applicationSecurityGroupName string - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -@description('Required. The name of the Load Balancer to create.') -param loadBalancerName string - -@description('Required. The name of the Recovery Services Vault to create.') -param recoveryServicesVaultName string - -@description('Required. The name of the Key Vault to create.') -param keyVaultName string - -@description('Required. The name of the Storage Account to create.') -param storageAccountName string - -@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') -param storageUploadDeploymentScriptName string - -@description('Required. The name of the Proximity Placement Group to create.') -param proximityPlacementGroupName string - -@description('Optional. The location to deploy resources to.') -param location string = resourceGroup().location - -var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' -var addressPrefix = '10.0.0.0/16' - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-04-01' = { - name: applicationSecurityGroupName - location: location -} - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(resourceGroup().id, 'Contributor', managedIdentity.id) - scope: resourceGroup() - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor - principalType: 'ServicePrincipal' - } -} - -resource loadBalancer 'Microsoft.Network/loadBalancers@2023-04-01' = { - name: loadBalancerName - location: location - sku: { - name: 'Standard' - } - properties: { - frontendIPConfigurations: [ - { - name: 'privateIPConfig1' - properties: { - subnet: virtualNetwork.properties.subnets[0] - } - } - ] - backendAddressPools: [ - { - name: 'servers' - } - ] - } -} - -resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-04-01' = { - name: recoveryServicesVaultName - location: location - sku: { - name: 'RS0' - tier: 'Standard' - } - properties: {} - - resource backupPolicy 'backupPolicies@2022-03-01' = { - name: 'backupPolicy' - properties: { - backupManagementType: 'AzureIaasVM' - instantRPDetails: {} - schedulePolicy: { - schedulePolicyType: 'SimpleSchedulePolicy' - scheduleRunFrequency: 'Daily' - scheduleRunTimes: [ - '2019-11-07T07:00:00Z' - ] - scheduleWeeklyFrequency: 0 - } - retentionPolicy: { - retentionPolicyType: 'LongTermRetentionPolicy' - dailySchedule: { - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 180 - durationType: 'Days' - } - } - weeklySchedule: { - daysOfTheWeek: [ - 'Sunday' - ] - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 12 - durationType: 'Weeks' - } - } - monthlySchedule: { - retentionScheduleFormatType: 'Weekly' - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' - ] - weeksOfTheMonth: [ - 'First' - ] - } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 60 - durationType: 'Months' - } - } - yearlySchedule: { - retentionScheduleFormatType: 'Weekly' - monthsOfYear: [ - 'January' - ] - retentionScheduleWeekly: { - daysOfTheWeek: [ - 'Sunday' - ] - weeksOfTheMonth: [ - 'First' - ] - } - retentionTimes: [ - '2019-11-07T07:00:00Z' - ] - retentionDuration: { - count: 10 - durationType: 'Years' - } - } - } - instantRpRetentionRangeInDays: 2 - timeZone: 'UTC' - protectedItemsCount: 0 - } - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: null - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] - } - - resource key 'keys@2022-07-01' = { - name: 'encryptionKey' - properties: { - kty: 'RSA' - } - } -} - -resource msiKVReadRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-KeyVault-Key-Read-RoleAssignment') - scope: keyVault::key - properties: { - principalId: managedIdentity.properties.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User - principalType: 'ServicePrincipal' - } -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { - name: storageAccountName - location: location - sku: { - name: 'Standard_LRS' - } - kind: 'StorageV2' - - resource blobService 'blobServices@2021-09-01' = { - name: 'default' - - resource container 'containers@2021-09-01' = { - name: 'scripts' - } - } -} - -resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { - name: storageUploadDeploymentScriptName - location: location - kind: 'AzurePowerShell' - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentity.id}': {} - } - } - properties: { - azPowerShellVersion: '9.0' - retentionInterval: 'P1D' - arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' - scriptContent: loadTextContent('../../../../../../utilities/e2e-template-assets/scripts/Set-BlobContent.ps1') - } - dependsOn: [ - msiRGContrRoleAssignment - ] -} - -resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { - name: proximityPlacementGroupName - location: location -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The resource ID of the created Application Security Group.') -output applicationSecurityGroupResourceId string = applicationSecurityGroup.id - -@description('The principal ID of the created Managed Identity.') -output managedIdentityPrincipalId string = managedIdentity.properties.principalId - -@description('The resource ID of the created Managed Identity.') -output managedIdentityResourceId string = managedIdentity.id - -@description('The resource ID of the created Load Balancer Backend Pool.') -output loadBalancerBackendPoolResourceId string = loadBalancer.properties.backendAddressPools[0].id - -@description('The name of the created Recovery Services Vault.') -output recoveryServicesVaultName string = recoveryServicesVault.name - -@description('The name of the Resource Group, the Recovery Services Vault was created in.') -output recoveryServicesVaultResourceGroupName string = resourceGroup().name - -@description('The name of the Backup Policy created in the Backup Recovery Vault.') -output recoveryServicesVaultBackupPolicyName string = recoveryServicesVault::backupPolicy.name - -@description('The resource ID of the created Key Vault.') -output keyVaultResourceId string = keyVault.id - -@description('The URL of the created Key Vault.') -output keyVaultUrl string = keyVault.properties.vaultUri - -@description('The URL of the created Key Vault Encryption Key.') -output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion - -@description('The resource ID of the created Storage Account.') -output storageAccountResourceId string = storageAccount.id - -@description('The name of the Custom Script Extension in the created Storage Account.') -output storageAccountCSEFileName string = storageAccountCSEFileName - -@description('The URL of the Custom Script Extension in the created Storage Account') -output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageAccount::blobService::container.name}/${storageAccountCSEFileName}' - -@description('The resource ID of the created Proximity Placement Group.') -output proximityPlacementGroupResourceId string = proximityPlacementGroup.id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep deleted file mode 100644 index 51e19418b8..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/windows.max/main.test.bicep +++ /dev/null @@ -1,331 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using large parameter set' -metadata description = 'This instance deploys the module with most of its features enabled.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'cvmwinmax' - -@description('Optional. The password to leverage for the login.') -@secure() -param password string = newGuid() - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - applicationSecurityGroupName: 'dep-${namePrefix}-asg-${serviceShort}' - managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' - keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}' - loadBalancerName: 'dep-${namePrefix}-lb-${serviceShort}' - recoveryServicesVaultName: 'dep-${namePrefix}-rsv-${serviceShort}' - storageAccountName: 'dep${namePrefix}sa${serviceShort}01' - storageUploadDeploymentScriptName: 'dep-${namePrefix}-sads-${serviceShort}' - proximityPlacementGroupName: 'dep-${namePrefix}-ppg-${serviceShort}' - } -} - -// Diagnostics -// =========== -module diagnosticDependencies '../../../../../../utilities/e2e-template-assets/templates/diagnostic.dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' - params: { - storageAccountName: 'dep${namePrefix}diasa${serviceShort}01' - logAnalyticsWorkspaceName: 'dep-${namePrefix}-law-${serviceShort}' - eventHubNamespaceEventHubName: 'dep-${namePrefix}-evh-${serviceShort}' - eventHubNamespaceName: 'dep-${namePrefix}-evhns-${serviceShort}' - location: location - } -} - -// ============== // -// Test Execution // -// ============== // - -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - name: '${namePrefix}${serviceShort}' - computerName: '${namePrefix}winvm1' - adminUsername: 'VMAdmin' - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2019-datacenter' - version: 'latest' - } - nicConfigurations: [ - { - deleteOption: 'Delete' - ipConfigurations: [ - { - applicationSecurityGroups: [ - { - id: nestedDependencies.outputs.applicationSecurityGroupResourceId - } - ] - loadBalancerBackendAddressPools: [ - { - id: nestedDependencies.outputs.loadBalancerBackendPoolResourceId - } - ] - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - } - zones: [ - '1' - '2' - '3' - ] - subnetResourceId: nestedDependencies.outputs.subnetResourceId - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - } - ] - nicSuffix: '-nic-01' - roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - diagnosticSettings: [ - { - name: 'customSetting' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - eventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName - eventHubAuthorizationRuleResourceId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId - storageAccountResourceId: diagnosticDependencies.outputs.storageAccountResourceId - workspaceResourceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId - } - ] - } - ] - osDisk: { - caching: 'ReadWrite' - createOption: 'fromImage' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - adminPassword: password - availabilityZone: 2 - backupPolicyName: nestedDependencies.outputs.recoveryServicesVaultBackupPolicyName - backupVaultName: nestedDependencies.outputs.recoveryServicesVaultName - backupVaultResourceGroup: nestedDependencies.outputs.recoveryServicesVaultResourceGroupName - dataDisks: [ - { - caching: 'None' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - { - caching: 'None' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - ] - enableAutomaticUpdates: true - patchMode: 'AutomaticByPlatform' - encryptionAtHost: false - extensionAntiMalwareConfig: { - enabled: true - settings: { - AntimalwareEnabled: 'true' - Exclusions: { - Extensions: '.ext1;.ext2' - Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' - Processes: 'excludedproc1.exe;excludedproc2.exe' - } - RealtimeProtectionEnabled: 'true' - ScheduledScanSettings: { - day: '7' - isEnabled: 'true' - scanType: 'Quick' - time: '120' - } - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: nestedDependencies.outputs.storageAccountResourceId - uri: nestedDependencies.outputs.storageAccountCSEFileUrl - } - ] - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionCustomScriptProtectedSetting: { - commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${nestedDependencies.outputs.storageAccountCSEFileName}"' - } - extensionDependencyAgentConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: nestedDependencies.outputs.keyVaultEncryptionKeyUrl - KeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId - KeyVaultURL: nestedDependencies.outputs.keyVaultUrl - ResizeOSDisk: 'false' - VolumeType: 'All' - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - } - extensionAadJoinConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionDSCConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionMonitoringAgentConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - extensionNetworkWatcherAgentConfig: { - enabled: true - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - proximityPlacementGroupResourceId: nestedDependencies.outputs.proximityPlacementGroupResourceId - roleAssignments: [ - { - roleDefinitionIdOrName: 'Owner' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - { - roleDefinitionIdOrName: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - principalId: nestedDependencies.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } - ] - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - nestedDependencies.outputs.managedIdentityResourceId - ] - } - tags: { - 'hidden-title': 'This is visible in the resource name' - Environment: 'Non-Prod' - Role: 'DeploymentValidation' - } - } -}] diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep deleted file mode 100644 index e5cb91cea0..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/dependencies.bicep +++ /dev/null @@ -1,92 +0,0 @@ -@description('Required. The name of the Virtual Network to create.') -param virtualNetworkName string - -@description('Required. The name of the Key Vault to create.') -param keyVaultName string - -@description('Required. The name of the Disk Encryption Set to create.') -param diskEncryptionSetName string - -@description('Optional. The location to deploy resources to.') -param location string = resourceGroup().location - -var addressPrefix = '10.0.0.0/16' - -resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-04-01' = { - name: virtualNetworkName - location: location - properties: { - addressSpace: { - addressPrefixes: [ - addressPrefix - ] - } - subnets: [ - { - name: 'defaultSubnet' - properties: { - addressPrefix: cidrSubnet(addressPrefix, 16, 0) - } - } - ] - } -} - -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { - name: keyVaultName - location: location - properties: { - sku: { - family: 'A' - name: 'standard' - } - tenantId: tenant().tenantId - enablePurgeProtection: true // Required by disk encryption set - softDeleteRetentionInDays: 7 - enabledForTemplateDeployment: true - enabledForDiskEncryption: true - enabledForDeployment: true - enableRbacAuthorization: true - accessPolicies: [] - } - - resource key 'keys@2022-07-01' = { - name: 'keyEncryptionKey' - properties: { - kty: 'RSA' - } - } -} - -resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { - name: diskEncryptionSetName - location: location - identity: { - type: 'SystemAssigned' - } - properties: { - activeKey: { - sourceVault: { - id: keyVault.id - } - keyUrl: keyVault::key.properties.keyUriWithVersion - } - encryptionType: 'EncryptionAtRestWithPlatformAndCustomerKeys' - } -} - -resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(keyVault::key.id, 'Key Vault Crypto User', diskEncryptionSet.id) - scope: keyVault - properties: { - principalId: diskEncryptionSet.identity.principalId - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e147488a-f6f5-4113-8e2d-b22465e65bf6') // Key Vault Crypto Service Encryption User - principalType: 'ServicePrincipal' - } -} - -@description('The resource ID of the created Virtual Network Subnet.') -output subnetResourceId string = virtualNetwork.properties.subnets[0].id - -@description('The resource ID of the created Disk Encryption Set.') -output diskEncryptionSetResourceId string = diskEncryptionSet.id diff --git a/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep b/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep deleted file mode 100644 index 66b285f155..0000000000 --- a/avm/res/compute/virtual-machine/tests/e2e/windows.ssecmk/main.test.bicep +++ /dev/null @@ -1,105 +0,0 @@ -targetScope = 'subscription' - -metadata name = 'Using disk encryption set for the VM.' -metadata description = 'This instance deploys the module with disk enryption set.' - -// ========== // -// Parameters // -// ========== // - -@description('Optional. The name of the resource group to deploy for testing purposes.') -@maxLength(90) -param resourceGroupName string = 'dep-${namePrefix}-compute.virtualMachines-${serviceShort}-rg' - -@description('Optional. The location to deploy resources to.') -param location string = deployment().location - -@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') -param serviceShort string = 'cvmwincmk' - -@description('Optional. The password to leverage for the login.') -@secure() -param password string = newGuid() - -@description('Generated. Used as a basis for unique resource names.') -param baseTime string = utcNow('u') - -@description('Optional. A token to inject into the name of each resource.') -param namePrefix string = '#_namePrefix_#' - -// ============ // -// Dependencies // -// ============ // - -// General resources -// ================= -resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { - name: resourceGroupName - location: location -} - -module nestedDependencies 'dependencies.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-nestedDependencies' - params: { - location: location - virtualNetworkName: 'dep-${namePrefix}-vnet-${serviceShort}' - // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) - keyVaultName: 'dep${namePrefix}kv${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' - diskEncryptionSetName: 'dep-${namePrefix}-des-${serviceShort}' - } -} - -// ============== // -// Test Execution // -// ============== // -@batchSize(1) -module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-test-${serviceShort}-${iteration}' - params: { - location: location - name: '${namePrefix}${serviceShort}' - adminUsername: 'VMAdministrator' - imageReference: { - publisher: 'MicrosoftWindowsServer' - offer: 'WindowsServer' - sku: '2019-datacenter' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - subnetResourceId: nestedDependencies.outputs.subnetResourceId - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - diskEncryptionSet: { - id: nestedDependencies.outputs.diskEncryptionSetResourceId - } - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - adminPassword: password - dataDisks: [ - { - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - diskEncryptionSet: { - id: nestedDependencies.outputs.diskEncryptionSetResourceId - } - } - } - ] - } -}] diff --git a/avm/res/compute/virtual-machine/version.json b/avm/res/compute/virtual-machine/version.json deleted file mode 100644 index 8def869ede..0000000000 --- a/avm/res/compute/virtual-machine/version.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://aka.ms/bicep-registry-module-version-file-schema#", - "version": "0.1", - "pathFilters": [ - "./main.json" - ] -} From 42ecc775a8ecffc0eed74eebbdbff534c92af3fc Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Thu, 4 Jan 2024 17:58:55 +0100 Subject: [PATCH 33/35] Update to latest --- avm/res/compute/virtual-machine/README.md | 2582 --------------------- 1 file changed, 2582 deletions(-) delete mode 100644 avm/res/compute/virtual-machine/README.md diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md deleted file mode 100644 index ab7f9d8f9a..0000000000 --- a/avm/res/compute/virtual-machine/README.md +++ /dev/null @@ -1,2582 +0,0 @@ -# Virtual Machines `[Microsoft.Compute/virtualMachines]` - -This module deploys a Virtual Machine with one or multiple NICs and optionally one or multiple public IPs. - -## Navigation - -- [Resource Types](#Resource-Types) -- [Usage examples](#Usage-examples) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) | -| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.Automanage/configurationProfileAssignments` | [2021-04-30-preview](https://learn.microsoft.com/en-us/azure/templates) | -| `Microsoft.Compute/virtualMachines` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines) | -| `Microsoft.Compute/virtualMachines/extensions` | [2022-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Compute/2022-11-01/virtualMachines/extensions) | -| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | -| `Microsoft.Network/networkInterfaces` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/networkInterfaces) | -| `Microsoft.Network/publicIPAddresses` | [2023-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-04-01/publicIPAddresses) | -| `Microsoft.RecoveryServices/vaults/backupFabrics/protectionContainers/protectedItems` | [2023-01-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.RecoveryServices/2023-01-01/vaults/backupFabrics/protectionContainers/protectedItems) | - -## Usage examples - -The following section provides usage examples for the module, which were used to validate and deploy the module successfully. For a full reference, please review the module's test folder in its repository. - ->**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. - ->**Note**: To reference the module, please use the following syntax `br/public:avm/res/compute/virtual-machine:`. - -- [Using automanage for the VM.](#example-1-using-automanage-for-the-vm) -- [Using only defaults](#example-2-using-only-defaults) -- [WAF-aligned](#example-3-waf-aligned) -- [Using only defaults](#example-4-using-only-defaults) -- [Using large parameter set](#example-5-using-large-parameter-set) -- [Using disk encryption set for the VM.](#example-6-using-disk-encryption-set-for-the-vm) - -### Example 1: _Using automanage for the VM._ - -This instance deploys the module with registering to an automation account. - - -

- -via Bicep module - -```bicep -module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, location)}-test-cvmlinatmg' - params: { - // Required parameters - adminUsername: 'localAdminUser' - imageReference: { - offer: '0001-com-ubuntu-server-jammy' - publisher: 'Canonical' - sku: '22_04-lts-gen2' - version: 'latest' - } - name: 'cvmlinatmg' - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - subnetResourceId: '' - zones: [ - '1' - '2' - '3' - ] - } - ] - nicSuffix: '-nic-01' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - ] - osDisk: { - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - vmSize: 'Standard_DS2_v2' - // Non-required parameters - configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' - disablePasswordAuthentication: true - location: '' - publicKeys: [ - { - keyData: '' - path: '/home/localAdminUser/.ssh/authorized_keys' - } - ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "adminUsername": { - "value": "localAdminUser" - }, - "imageReference": { - "value": { - "offer": "0001-com-ubuntu-server-jammy", - "publisher": "Canonical", - "sku": "22_04-lts-gen2", - "version": "latest" - } - }, - "name": { - "value": "cvmlinatmg" - }, - "nicConfigurations": { - "value": [ - { - "ipConfigurations": [ - { - "name": "ipconfig01", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01", - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - }, - "subnetResourceId": "", - "zones": [ - "1", - "2", - "3" - ] - } - ], - "nicSuffix": "-nic-01", - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - ] - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Linux" - }, - "vmSize": { - "value": "Standard_DS2_v2" - }, - // Non-required parameters - "configurationProfile": { - "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" - }, - "disablePasswordAuthentication": { - "value": true - }, - "location": { - "value": "" - }, - "publicKeys": { - "value": [ - { - "keyData": "", - "path": "/home/localAdminUser/.ssh/authorized_keys" - } - ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - } -} -``` - -
-

- -### Example 2: _Using only defaults_ - -This instance deploys the module with the minimum set of required parameters. - - -

- -via Bicep module - -```bicep -module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, location)}-test-cvmlinmin' - params: { - // Required parameters - adminUsername: 'localAdminUser' - imageReference: { - offer: '0001-com-ubuntu-server-jammy' - publisher: 'Canonical' - sku: '22_04-lts-gen2' - version: 'latest' - } - name: 'cvmlinmin' - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - } - subnetResourceId: '' - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - caching: 'ReadWrite' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - vmSize: 'Standard_DS2_v2' - // Non-required parameters - disablePasswordAuthentication: true - location: '' - publicKeys: [ - { - keyData: '' - path: '/home/localAdminUser/.ssh/authorized_keys' - } - ] - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "adminUsername": { - "value": "localAdminUser" - }, - "imageReference": { - "value": { - "offer": "0001-com-ubuntu-server-jammy", - "publisher": "Canonical", - "sku": "22_04-lts-gen2", - "version": "latest" - } - }, - "name": { - "value": "cvmlinmin" - }, - "nicConfigurations": { - "value": [ - { - "ipConfigurations": [ - { - "name": "ipconfig01", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01" - }, - "subnetResourceId": "" - } - ], - "nicSuffix": "-nic-01" - } - ] - }, - "osDisk": { - "value": { - "caching": "ReadWrite", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Linux" - }, - "vmSize": { - "value": "Standard_DS2_v2" - }, - // Non-required parameters - "disablePasswordAuthentication": { - "value": true - }, - "location": { - "value": "" - }, - "publicKeys": { - "value": [ - { - "keyData": "", - "path": "/home/localAdminUser/.ssh/authorized_keys" - } - ] - } - } -} -``` - -
-

- -### Example 3: _WAF-aligned_ - -This instance deploys the module in alignment with the best-practices of the Well-Architected Framework. - - -

- -via Bicep module - -```bicep -module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, location)}-test-cvmwinwaf' - params: { - // Required parameters - adminUsername: 'VMAdmin' - imageReference: { - offer: 'WindowsServer' - publisher: 'MicrosoftWindowsServer' - sku: '2019-datacenter' - version: 'latest' - } - name: 'cvmwinwaf' - nicConfigurations: [ - { - deleteOption: 'Delete' - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - ipConfigurations: [ - { - applicationSecurityGroups: [ - { - id: '' - } - ] - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - loadBalancerBackendAddressPools: [ - { - id: '' - } - ] - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - } - subnetResourceId: '' - zones: [ - '1' - '2' - '3' - ] - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - caching: 'ReadWrite' - createOption: 'fromImage' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - // Non-required parameters - adminPassword: '' - availabilityZone: 2 - backupPolicyName: '' - backupVaultName: '' - backupVaultResourceGroup: '' - computerName: 'winvm1' - dataDisks: [ - { - caching: 'ReadOnly' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - { - caching: 'ReadOnly' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - ] - enableAutomaticUpdates: true - encryptionAtHost: false - extensionAadJoinConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionAntiMalwareConfig: { - enabled: true - settings: { - AntimalwareEnabled: 'true' - Exclusions: { - Extensions: '.ext1;.ext2' - Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' - Processes: 'excludedproc1.exe;excludedproc2.exe' - } - RealtimeProtectionEnabled: 'true' - ScheduledScanSettings: { - day: '7' - isEnabled: 'true' - scanType: 'Quick' - time: '120' - } - } - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: '' - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: '' - KeyVaultResourceId: '' - KeyVaultURL: '' - ResizeOSDisk: 'false' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - VolumeType: 'All' - } - } - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: '' - uri: '' - } - ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionCustomScriptProtectedSetting: { - commandToExecute: '' - } - extensionDependencyAgentConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionDSCConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionMonitoringAgentConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionNetworkWatcherAgentConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - patchMode: 'AutomaticByPlatform' - proximityPlacementGroupResourceId: '' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "adminUsername": { - "value": "VMAdmin" - }, - "imageReference": { - "value": { - "offer": "WindowsServer", - "publisher": "MicrosoftWindowsServer", - "sku": "2019-datacenter", - "version": "latest" - } - }, - "name": { - "value": "cvmwinwaf" - }, - "nicConfigurations": { - "value": [ - { - "deleteOption": "Delete", - "diagnosticSettings": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ], - "ipConfigurations": [ - { - "applicationSecurityGroups": [ - { - "id": "" - } - ], - "diagnosticSettings": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ], - "loadBalancerBackendAddressPools": [ - { - "id": "" - } - ], - "name": "ipconfig01", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01" - }, - "subnetResourceId": "", - "zones": [ - "1", - "2", - "3" - ] - } - ], - "nicSuffix": "-nic-01" - } - ] - }, - "osDisk": { - "value": { - "caching": "ReadWrite", - "createOption": "fromImage", - "deleteOption": "Delete", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_DS2_v2" - }, - // Non-required parameters - "adminPassword": { - "value": "" - }, - "availabilityZone": { - "value": 2 - }, - "backupPolicyName": { - "value": "" - }, - "backupVaultName": { - "value": "" - }, - "backupVaultResourceGroup": { - "value": "" - }, - "computerName": { - "value": "winvm1" - }, - "dataDisks": { - "value": [ - { - "caching": "ReadOnly", - "createOption": "Empty", - "deleteOption": "Delete", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - }, - { - "caching": "ReadOnly", - "createOption": "Empty", - "deleteOption": "Delete", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - ] - }, - "enableAutomaticUpdates": { - "value": true - }, - "encryptionAtHost": { - "value": false - }, - "extensionAadJoinConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionAntiMalwareConfig": { - "value": { - "enabled": true, - "settings": { - "AntimalwareEnabled": "true", - "Exclusions": { - "Extensions": ".ext1;.ext2", - "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", - "Processes": "excludedproc1.exe;excludedproc2.exe" - }, - "RealtimeProtectionEnabled": "true", - "ScheduledScanSettings": { - "day": "7", - "isEnabled": "true", - "scanType": "Quick", - "time": "120" - } - }, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionAzureDiskEncryptionConfig": { - "value": { - "enabled": true, - "settings": { - "EncryptionOperation": "EnableEncryption", - "KekVaultResourceId": "", - "KeyEncryptionAlgorithm": "RSA-OAEP", - "KeyEncryptionKeyURL": "", - "KeyVaultResourceId": "", - "KeyVaultURL": "", - "ResizeOSDisk": "false", - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - }, - "VolumeType": "All" - } - } - }, - "extensionCustomScriptConfig": { - "value": { - "enabled": true, - "fileData": [ - { - "storageAccountId": "", - "uri": "" - } - ], - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionCustomScriptProtectedSetting": { - "value": { - "commandToExecute": "" - } - }, - "extensionDependencyAgentConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionDSCConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionMonitoringAgentConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionNetworkWatcherAgentConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "location": { - "value": "" - }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "patchMode": { - "value": "AutomaticByPlatform" - }, - "proximityPlacementGroupResourceId": { - "value": "" - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - } -} -``` - -
-

- -### Example 4: _Using only defaults_ - -This instance deploys the module with the minimum set of required parameters. - - -

- -via Bicep module - -```bicep -module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, location)}-test-cvmwinmin' - params: { - // Required parameters - adminUsername: 'localAdminUser' - imageReference: { - offer: 'WindowsServer' - publisher: 'MicrosoftWindowsServer' - sku: '2022-datacenter-azure-edition' - version: 'latest' - } - name: 'cvmwinmin' - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - subnetResourceId: '' - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - caching: 'ReadWrite' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - // Non-required parameters - adminPassword: '' - location: '' - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "adminUsername": { - "value": "localAdminUser" - }, - "imageReference": { - "value": { - "offer": "WindowsServer", - "publisher": "MicrosoftWindowsServer", - "sku": "2022-datacenter-azure-edition", - "version": "latest" - } - }, - "name": { - "value": "cvmwinmin" - }, - "nicConfigurations": { - "value": [ - { - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "" - } - ], - "nicSuffix": "-nic-01" - } - ] - }, - "osDisk": { - "value": { - "caching": "ReadWrite", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_DS2_v2" - }, - // Non-required parameters - "adminPassword": { - "value": "" - }, - "location": { - "value": "" - } - } -} -``` - -
-

- -### Example 5: _Using large parameter set_ - -This instance deploys the module with most of its features enabled. - - -

- -via Bicep module - -```bicep -module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, location)}-test-cvmwinmax' - params: { - // Required parameters - adminUsername: 'VMAdmin' - imageReference: { - offer: 'WindowsServer' - publisher: 'MicrosoftWindowsServer' - sku: '2019-datacenter' - version: 'latest' - } - name: 'cvmwinmax' - nicConfigurations: [ - { - deleteOption: 'Delete' - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - ipConfigurations: [ - { - applicationSecurityGroups: [ - { - id: '' - } - ] - diagnosticSettings: [ - { - eventHubAuthorizationRuleResourceId: '' - eventHubName: '' - metricCategories: [ - { - category: 'AllMetrics' - } - ] - name: 'customSetting' - storageAccountResourceId: '' - workspaceResourceId: '' - } - ] - loadBalancerBackendAddressPools: [ - { - id: '' - } - ] - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Reader' - } - ] - } - subnetResourceId: '' - zones: [ - '1' - '2' - '3' - ] - } - ] - nicSuffix: '-nic-01' - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Reader' - } - ] - } - ] - osDisk: { - caching: 'ReadWrite' - createOption: 'fromImage' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - // Non-required parameters - adminPassword: '' - availabilityZone: 2 - backupPolicyName: '' - backupVaultName: '' - backupVaultResourceGroup: '' - computerName: 'winvm1' - dataDisks: [ - { - caching: 'None' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - { - caching: 'None' - createOption: 'Empty' - deleteOption: 'Delete' - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - ] - enableAutomaticUpdates: true - encryptionAtHost: false - extensionAadJoinConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionAntiMalwareConfig: { - enabled: true - settings: { - AntimalwareEnabled: 'true' - Exclusions: { - Extensions: '.ext1;.ext2' - Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' - Processes: 'excludedproc1.exe;excludedproc2.exe' - } - RealtimeProtectionEnabled: 'true' - ScheduledScanSettings: { - day: '7' - isEnabled: 'true' - scanType: 'Quick' - time: '120' - } - } - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionAzureDiskEncryptionConfig: { - enabled: true - settings: { - EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: '' - KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: '' - KeyVaultResourceId: '' - KeyVaultURL: '' - ResizeOSDisk: 'false' - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - VolumeType: 'All' - } - } - extensionCustomScriptConfig: { - enabled: true - fileData: [ - { - storageAccountId: '' - uri: '' - } - ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionCustomScriptProtectedSetting: { - commandToExecute: '' - } - extensionDependencyAgentConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionDSCConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionMonitoringAgentConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - extensionNetworkWatcherAgentConfig: { - enabled: true - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } - location: '' - lock: { - kind: 'CanNotDelete' - name: 'myCustomLockName' - } - managedIdentities: { - systemAssigned: true - userAssignedResourceIds: [ - '' - ] - } - patchMode: 'AutomaticByPlatform' - proximityPlacementGroupResourceId: '' - roleAssignments: [ - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'Owner' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: 'b24988ac-6180-42a0-ab88-20f7382dd24c' - } - { - principalId: '' - principalType: 'ServicePrincipal' - roleDefinitionIdOrName: '' - } - ] - tags: { - Environment: 'Non-Prod' - 'hidden-title': 'This is visible in the resource name' - Role: 'DeploymentValidation' - } - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "adminUsername": { - "value": "VMAdmin" - }, - "imageReference": { - "value": { - "offer": "WindowsServer", - "publisher": "MicrosoftWindowsServer", - "sku": "2019-datacenter", - "version": "latest" - } - }, - "name": { - "value": "cvmwinmax" - }, - "nicConfigurations": { - "value": [ - { - "deleteOption": "Delete", - "diagnosticSettings": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ], - "ipConfigurations": [ - { - "applicationSecurityGroups": [ - { - "id": "" - } - ], - "diagnosticSettings": [ - { - "eventHubAuthorizationRuleResourceId": "", - "eventHubName": "", - "metricCategories": [ - { - "category": "AllMetrics" - } - ], - "name": "customSetting", - "storageAccountResourceId": "", - "workspaceResourceId": "" - } - ], - "loadBalancerBackendAddressPools": [ - { - "id": "" - } - ], - "name": "ipconfig01", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01", - "roleAssignments": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" - } - ] - }, - "subnetResourceId": "", - "zones": [ - "1", - "2", - "3" - ] - } - ], - "nicSuffix": "-nic-01", - "roleAssignments": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Reader" - } - ] - } - ] - }, - "osDisk": { - "value": { - "caching": "ReadWrite", - "createOption": "fromImage", - "deleteOption": "Delete", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_DS2_v2" - }, - // Non-required parameters - "adminPassword": { - "value": "" - }, - "availabilityZone": { - "value": 2 - }, - "backupPolicyName": { - "value": "" - }, - "backupVaultName": { - "value": "" - }, - "backupVaultResourceGroup": { - "value": "" - }, - "computerName": { - "value": "winvm1" - }, - "dataDisks": { - "value": [ - { - "caching": "None", - "createOption": "Empty", - "deleteOption": "Delete", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - }, - { - "caching": "None", - "createOption": "Empty", - "deleteOption": "Delete", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - ] - }, - "enableAutomaticUpdates": { - "value": true - }, - "encryptionAtHost": { - "value": false - }, - "extensionAadJoinConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionAntiMalwareConfig": { - "value": { - "enabled": true, - "settings": { - "AntimalwareEnabled": "true", - "Exclusions": { - "Extensions": ".ext1;.ext2", - "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", - "Processes": "excludedproc1.exe;excludedproc2.exe" - }, - "RealtimeProtectionEnabled": "true", - "ScheduledScanSettings": { - "day": "7", - "isEnabled": "true", - "scanType": "Quick", - "time": "120" - } - }, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionAzureDiskEncryptionConfig": { - "value": { - "enabled": true, - "settings": { - "EncryptionOperation": "EnableEncryption", - "KekVaultResourceId": "", - "KeyEncryptionAlgorithm": "RSA-OAEP", - "KeyEncryptionKeyURL": "", - "KeyVaultResourceId": "", - "KeyVaultURL": "", - "ResizeOSDisk": "false", - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - }, - "VolumeType": "All" - } - } - }, - "extensionCustomScriptConfig": { - "value": { - "enabled": true, - "fileData": [ - { - "storageAccountId": "", - "uri": "" - } - ], - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionCustomScriptProtectedSetting": { - "value": { - "commandToExecute": "" - } - }, - "extensionDependencyAgentConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionDSCConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionMonitoringAgentConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "extensionNetworkWatcherAgentConfig": { - "value": { - "enabled": true, - "tags": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - }, - "location": { - "value": "" - }, - "lock": { - "value": { - "kind": "CanNotDelete", - "name": "myCustomLockName" - } - }, - "managedIdentities": { - "value": { - "systemAssigned": true, - "userAssignedResourceIds": [ - "" - ] - } - }, - "patchMode": { - "value": "AutomaticByPlatform" - }, - "proximityPlacementGroupResourceId": { - "value": "" - }, - "roleAssignments": { - "value": [ - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "Owner" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "b24988ac-6180-42a0-ab88-20f7382dd24c" - }, - { - "principalId": "", - "principalType": "ServicePrincipal", - "roleDefinitionIdOrName": "" - } - ] - }, - "tags": { - "value": { - "Environment": "Non-Prod", - "hidden-title": "This is visible in the resource name", - "Role": "DeploymentValidation" - } - } - } -} -``` - -
-

- -### Example 6: _Using disk encryption set for the VM._ - -This instance deploys the module with disk enryption set. - - -

- -via Bicep module - -```bicep -module virtualMachine 'br/public:avm/res/compute/virtual-machine:' = { - name: '${uniqueString(deployment().name, location)}-test-cvmwincmk' - params: { - // Required parameters - adminUsername: 'VMAdministrator' - imageReference: { - offer: 'WindowsServer' - publisher: 'MicrosoftWindowsServer' - sku: '2019-datacenter' - version: 'latest' - } - name: 'cvmwincmk' - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - subnetResourceId: '' - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - diskSizeGB: '128' - managedDisk: { - diskEncryptionSet: { - id: '' - } - storageAccountType: 'Premium_LRS' - } - } - osType: 'Windows' - vmSize: 'Standard_DS2_v2' - // Non-required parameters - adminPassword: '' - dataDisks: [ - { - diskSizeGB: '128' - managedDisk: { - diskEncryptionSet: { - id: '' - } - storageAccountType: 'Premium_LRS' - } - } - ] - location: '' - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "adminUsername": { - "value": "VMAdministrator" - }, - "imageReference": { - "value": { - "offer": "WindowsServer", - "publisher": "MicrosoftWindowsServer", - "sku": "2019-datacenter", - "version": "latest" - } - }, - "name": { - "value": "cvmwincmk" - }, - "nicConfigurations": { - "value": [ - { - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "" - } - ], - "nicSuffix": "-nic-01" - } - ] - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "diskEncryptionSet": { - "id": "" - }, - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_DS2_v2" - }, - // Non-required parameters - "adminPassword": { - "value": "" - }, - "dataDisks": { - "value": [ - { - "diskSizeGB": "128", - "managedDisk": { - "diskEncryptionSet": { - "id": "" - }, - "storageAccountType": "Premium_LRS" - } - } - ] - }, - "location": { - "value": "" - } - } -} -``` - -
-

- - -## Parameters - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`adminUsername`](#parameter-adminusername) | securestring | Administrator username. | -| [`configurationProfile`](#parameter-configurationprofile) | string | The configuration profile of automanage. | -| [`imageReference`](#parameter-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. | -| [`name`](#parameter-name) | string | The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. | -| [`nicConfigurations`](#parameter-nicconfigurations) | array | Configures NICs and PIPs. | -| [`osDisk`](#parameter-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`](#parameter-ostype) | string | The chosen OS type. | -| [`vmSize`](#parameter-vmsize) | string | Specifies the size for the VMs. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`additionalUnattendContent`](#parameter-additionalunattendcontent) | array | Specifies additional XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied. | -| [`adminPassword`](#parameter-adminpassword) | securestring | When specifying a Windows Virtual Machine, this value should be passed. | -| [`allowExtensionOperations`](#parameter-allowextensionoperations) | bool | 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. | -| [`availabilitySetResourceId`](#parameter-availabilitysetresourceid) | string | Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set. | -| [`availabilityZone`](#parameter-availabilityzone) | int | 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`](#parameter-backuppolicyname) | string | Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. | -| [`backupVaultName`](#parameter-backupvaultname) | string | Recovery service vault name to add VMs to backup. | -| [`backupVaultResourceGroup`](#parameter-backupvaultresourcegroup) | string | Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. | -| [`bootDiagnostics`](#parameter-bootdiagnostics) | bool | Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled. | -| [`bootDiagnosticStorageAccountName`](#parameter-bootdiagnosticstorageaccountname) | string | Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided. | -| [`bootDiagnosticStorageAccountUri`](#parameter-bootdiagnosticstorageaccounturi) | string | Storage account boot diagnostic base URI. | -| [`certificatesToBeInstalled`](#parameter-certificatestobeinstalled) | array | Specifies set of certificates that should be installed onto the virtual machine. | -| [`computerName`](#parameter-computername) | string | Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name. | -| [`customData`](#parameter-customdata) | string | Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. | -| [`dataDisks`](#parameter-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`](#parameter-dedicatedhostid) | string | Specifies resource ID about the dedicated host that the virtual machine resides in. | -| [`disablePasswordAuthentication`](#parameter-disablepasswordauthentication) | bool | Specifies whether password authentication should be disabled. | -| [`enableAutomaticUpdates`](#parameter-enableautomaticupdates) | bool | Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. | -| [`enableEvictionPolicy`](#parameter-enableevictionpolicy) | bool | Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. | -| [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | -| [`encryptionAtHost`](#parameter-encryptionathost) | bool | 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. | -| [`extensionAadJoinConfig`](#parameter-extensionaadjoinconfig) | object | The configuration for the [AAD Join] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionAntiMalwareConfig`](#parameter-extensionantimalwareconfig) | object | The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionAzureDiskEncryptionConfig`](#parameter-extensionazurediskencryptionconfig) | object | The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys. | -| [`extensionCustomScriptConfig`](#parameter-extensioncustomscriptconfig) | object | The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionCustomScriptProtectedSetting`](#parameter-extensioncustomscriptprotectedsetting) | secureObject | Any object that contains the extension specific protected settings. | -| [`extensionDependencyAgentConfig`](#parameter-extensiondependencyagentconfig) | object | The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionDomainJoinConfig`](#parameter-extensiondomainjoinconfig) | object | The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionDomainJoinPassword`](#parameter-extensiondomainjoinpassword) | securestring | Required if name is specified. Password of the user specified in user parameter. | -| [`extensionDSCConfig`](#parameter-extensiondscconfig) | object | The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionMonitoringAgentConfig`](#parameter-extensionmonitoringagentconfig) | object | The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`extensionNetworkWatcherAgentConfig`](#parameter-extensionnetworkwatcheragentconfig) | object | The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed. | -| [`licenseType`](#parameter-licensetype) | string | 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`](#parameter-location) | string | Location for all resources. | -| [`lock`](#parameter-lock) | object | The lock settings of the service. | -| [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = "True". | -| [`maxPriceForLowPriorityVm`](#parameter-maxpriceforlowpriorityvm) | string | Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. | -| [`patchAssessmentMode`](#parameter-patchassessmentmode) | string | VM guest patching assessment mode. Set it to 'AutomaticByPlatform' to enable automatically check for updates every 24 hours. | -| [`patchMode`](#parameter-patchmode) | string | VM guest patching orchestration mode. 'AutomaticByOS' & 'Manual' are for Windows only, 'ImageDefault' for Linux only. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'. | -| [`plan`](#parameter-plan) | 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. | -| [`priority`](#parameter-priority) | string | Specifies the priority for the virtual machine. | -| [`provisionVMAgent`](#parameter-provisionvmagent) | bool | 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. | -| [`proximityPlacementGroupResourceId`](#parameter-proximityplacementgroupresourceid) | string | Resource ID of a proximity placement group. | -| [`publicKeys`](#parameter-publickeys) | array | The list of SSH public keys used to authenticate with linux based VMs. | -| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. | -| [`sasTokenValidityLength`](#parameter-sastokenvaliditylength) | string | 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`](#parameter-securebootenabled) | bool | 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`](#parameter-securitytype) | string | Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. | -| [`tags`](#parameter-tags) | object | Tags of the resource. | -| [`timeZone`](#parameter-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`](#parameter-ultrassdenabled) | bool | 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. | -| [`vTpmEnabled`](#parameter-vtpmenabled) | bool | 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`](#parameter-winrm) | array | Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. | - -**Generated parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`baseTime`](#parameter-basetime) | string | Do not provide a value! This date value is used to generate a registration token. | - -### Parameter: `adminUsername` - -Administrator username. - -- Required: Yes -- Type: securestring - -### Parameter: `configurationProfile` - -The configuration profile of automanage. - -- Required: No -- Type: string -- Default: `''` -- Allowed: - ```Bicep - [ - '' - '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesDevTest' - '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' - ] - ``` - -### Parameter: `imageReference` - -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. - -- Required: Yes -- Type: object - -### Parameter: `name` - -The name of the virtual machine to be created. You should use a unique prefix to reduce name collisions in Active Directory. - -- Required: Yes -- Type: string - -### Parameter: `nicConfigurations` - -Configures NICs and PIPs. - -- Required: Yes -- Type: array - -### Parameter: `osDisk` - -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. - -- Required: Yes -- Type: object - -### Parameter: `osType` - -The chosen OS type. - -- Required: Yes -- Type: string -- Allowed: - ```Bicep - [ - 'Linux' - 'Windows' - ] - ``` - -### Parameter: `vmSize` - -Specifies the size for the VMs. - -- Required: Yes -- Type: string - -### Parameter: `additionalUnattendContent` - -Specifies additional XML formatted information that can be included in the Unattend.xml file, which is used by Windows Setup. Contents are defined by setting name, component name, and the pass in which the content is applied. - -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `adminPassword` - -When specifying a Windows Virtual Machine, this value should be passed. - -- Required: No -- Type: securestring -- Default: `''` - -### Parameter: `allowExtensionOperations` - -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. - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `availabilitySetResourceId` - -Resource ID of an availability set. Cannot be used in combination with availability zone nor scale set. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `availabilityZone` - -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. - -- Required: No -- Type: int -- Default: `0` -- Allowed: - ```Bicep - [ - 0 - 1 - 2 - 3 - ] - ``` - -### Parameter: `backupPolicyName` - -Backup policy the VMs should be using for backup. If not provided, it will use the DefaultPolicy from the backup recovery service vault. - -- Required: No -- Type: string -- Default: `'DefaultPolicy'` - -### Parameter: `backupVaultName` - -Recovery service vault name to add VMs to backup. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `backupVaultResourceGroup` - -Resource group of the backup recovery service vault. If not provided the current resource group name is considered by default. - -- Required: No -- Type: string -- Default: `[resourceGroup().name]` - -### Parameter: `bootDiagnostics` - -Whether boot diagnostics should be enabled on the Virtual Machine. Boot diagnostics will be enabled with a managed storage account if no bootDiagnosticsStorageAccountName value is provided. If bootDiagnostics and bootDiagnosticsStorageAccountName values are not provided, boot diagnostics will be disabled. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `bootDiagnosticStorageAccountName` - -Custom storage account used to store boot diagnostic information. Boot diagnostics will be enabled with a custom storage account if a value is provided. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `bootDiagnosticStorageAccountUri` - -Storage account boot diagnostic base URI. - -- Required: No -- Type: string -- Default: `[format('.blob.{0}/', environment().suffixes.storage)]` - -### Parameter: `certificatesToBeInstalled` - -Specifies set of certificates that should be installed onto the virtual machine. - -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `computerName` - -Can be used if the computer name needs to be different from the Azure VM resource name. If not used, the resource name will be used as computer name. - -- Required: No -- Type: string -- Default: `[parameters('name')]` - -### Parameter: `customData` - -Custom data associated to the VM, this value will be automatically converted into base64 to account for the expected VM format. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `dataDisks` - -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. - -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `dedicatedHostId` - -Specifies resource ID about the dedicated host that the virtual machine resides in. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `disablePasswordAuthentication` - -Specifies whether password authentication should be disabled. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `enableAutomaticUpdates` - -Indicates whether Automatic Updates is enabled for the Windows virtual machine. Default value is true. When patchMode is set to Manual, this parameter must be set to false. For virtual machine scale sets, this property can be updated and updates will take effect on OS reprovisioning. - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `enableEvictionPolicy` - -Specifies the eviction policy for the low priority virtual machine. Will result in 'Deallocate' eviction policy. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `enableTelemetry` - -Enable telemetry via a Globally Unique Identifier (GUID). - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `encryptionAtHost` - -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. - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `extensionAadJoinConfig` - -The configuration for the [AAD Join] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionAntiMalwareConfig` - -The configuration for the [Anti Malware] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionAzureDiskEncryptionConfig` - -The configuration for the [Azure Disk Encryption] extension. Must at least contain the ["enabled": true] property to be executed. Restrictions: Cannot be enabled on disks that have encryption at host enabled. Managed disks encrypted using Azure Disk Encryption cannot be encrypted using customer-managed keys. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionCustomScriptConfig` - -The configuration for the [Custom Script] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - fileData: [] - } - ``` - -### Parameter: `extensionCustomScriptProtectedSetting` - -Any object that contains the extension specific protected settings. - -- Required: No -- Type: secureObject -- Default: `{}` - -### Parameter: `extensionDependencyAgentConfig` - -The configuration for the [Dependency Agent] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionDomainJoinConfig` - -The configuration for the [Domain Join] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionDomainJoinPassword` - -Required if name is specified. Password of the user specified in user parameter. - -- Required: No -- Type: securestring -- Default: `''` - -### Parameter: `extensionDSCConfig` - -The configuration for the [Desired State Configuration] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionMonitoringAgentConfig` - -The configuration for the [Monitoring Agent] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `extensionNetworkWatcherAgentConfig` - -The configuration for the [Network Watcher Agent] extension. Must at least contain the ["enabled": true] property to be executed. - -- Required: No -- Type: object -- Default: - ```Bicep - { - enabled: false - } - ``` - -### Parameter: `licenseType` - -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. - -- Required: No -- Type: string -- Default: `''` -- Allowed: - ```Bicep - [ - '' - 'Windows_Client' - 'Windows_Server' - ] - ``` - -### Parameter: `location` - -Location for all resources. - -- Required: No -- Type: string -- Default: `[resourceGroup().location]` - -### Parameter: `lock` - -The lock settings of the service. - -- Required: No -- Type: object - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`kind`](#parameter-lockkind) | string | Specify the type of lock. | -| [`name`](#parameter-lockname) | string | Specify the name of lock. | - -### Parameter: `lock.kind` - -Specify the type of lock. - -- Required: No -- Type: string -- Allowed: - ```Bicep - [ - 'CanNotDelete' - 'None' - 'ReadOnly' - ] - ``` - -### Parameter: `lock.name` - -Specify the name of lock. - -- Required: No -- Type: string - -### Parameter: `managedIdentities` - -The managed identity definition for this resource. The system-assigned managed identity will automatically be enabled if extensionAadJoinConfig.enabled = "True". - -- Required: No -- Type: object - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`systemAssigned`](#parameter-managedidentitiessystemassigned) | bool | Enables system assigned managed identity on the resource. | -| [`userAssignedResourceIds`](#parameter-managedidentitiesuserassignedresourceids) | array | The resource ID(s) to assign to the resource. | - -### Parameter: `managedIdentities.systemAssigned` - -Enables system assigned managed identity on the resource. - -- Required: No -- Type: bool - -### Parameter: `managedIdentities.userAssignedResourceIds` - -The resource ID(s) to assign to the resource. - -- Required: No -- Type: array - -### Parameter: `maxPriceForLowPriorityVm` - -Specifies the maximum price you are willing to pay for a low priority VM/VMSS. This price is in US Dollars. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `patchAssessmentMode` - -VM guest patching assessment mode. Set it to 'AutomaticByPlatform' to enable automatically check for updates every 24 hours. - -- Required: No -- Type: string -- Default: `'ImageDefault'` -- Allowed: - ```Bicep - [ - 'AutomaticByPlatform' - 'ImageDefault' - ] - ``` - -### Parameter: `patchMode` - -VM guest patching orchestration mode. 'AutomaticByOS' & 'Manual' are for Windows only, 'ImageDefault' for Linux only. Refer to 'https://learn.microsoft.com/en-us/azure/virtual-machines/automatic-vm-guest-patching'. - -- Required: No -- Type: string -- Default: `''` -- Allowed: - ```Bicep - [ - '' - 'AutomaticByOS' - 'AutomaticByPlatform' - 'ImageDefault' - 'Manual' - ] - ``` - -### Parameter: `plan` - -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. - -- Required: No -- Type: object -- Default: `{}` - -### Parameter: `priority` - -Specifies the priority for the virtual machine. - -- Required: No -- Type: string -- Default: `'Regular'` -- Allowed: - ```Bicep - [ - 'Low' - 'Regular' - 'Spot' - ] - ``` - -### Parameter: `provisionVMAgent` - -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. - -- Required: No -- Type: bool -- Default: `True` - -### Parameter: `proximityPlacementGroupResourceId` - -Resource ID of a proximity placement group. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `publicKeys` - -The list of SSH public keys used to authenticate with linux based VMs. - -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `roleAssignments` - -Array of role assignments to create. - -- Required: No -- Type: array - -**Required parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`principalId`](#parameter-roleassignmentsprincipalid) | string | The principal ID of the principal (user/group/identity) to assign the role to. | -| [`roleDefinitionIdOrName`](#parameter-roleassignmentsroledefinitionidorname) | string | The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`condition`](#parameter-roleassignmentscondition) | string | The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" | -| [`conditionVersion`](#parameter-roleassignmentsconditionversion) | string | Version of the condition. | -| [`delegatedManagedIdentityResourceId`](#parameter-roleassignmentsdelegatedmanagedidentityresourceid) | string | The Resource Id of the delegated managed identity resource. | -| [`description`](#parameter-roleassignmentsdescription) | string | The description of the role assignment. | -| [`principalType`](#parameter-roleassignmentsprincipaltype) | string | The principal type of the assigned principal ID. | - -### Parameter: `roleAssignments.principalId` - -The principal ID of the principal (user/group/identity) to assign the role to. - -- Required: Yes -- Type: string - -### Parameter: `roleAssignments.roleDefinitionIdOrName` - -The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. - -- Required: Yes -- Type: string - -### Parameter: `roleAssignments.condition` - -The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container" - -- Required: No -- Type: string - -### Parameter: `roleAssignments.conditionVersion` - -Version of the condition. - -- Required: No -- Type: string -- Allowed: - ```Bicep - [ - '2.0' - ] - ``` - -### Parameter: `roleAssignments.delegatedManagedIdentityResourceId` - -The Resource Id of the delegated managed identity resource. - -- Required: No -- Type: string - -### Parameter: `roleAssignments.description` - -The description of the role assignment. - -- Required: No -- Type: string - -### Parameter: `roleAssignments.principalType` - -The principal type of the assigned principal ID. - -- Required: No -- Type: string -- Allowed: - ```Bicep - [ - 'Device' - 'ForeignGroup' - 'Group' - 'ServicePrincipal' - 'User' - ] - ``` - -### Parameter: `sasTokenValidityLength` - -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. - -- Required: No -- Type: string -- Default: `'PT8H'` - -### Parameter: `secureBootEnabled` - -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. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `securityType` - -Specifies the SecurityType of the virtual machine. It is set as TrustedLaunch to enable UefiSettings. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `tags` - -Tags of the resource. - -- Required: No -- Type: object - -### Parameter: `timeZone` - -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`. - -- Required: No -- Type: string -- Default: `''` - -### Parameter: `ultraSSDEnabled` - -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. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `vTpmEnabled` - -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. - -- Required: No -- Type: bool -- Default: `False` - -### Parameter: `winRM` - -Specifies the Windows Remote Management listeners. This enables remote Windows PowerShell. - WinRMConfiguration object. - -- Required: No -- Type: array -- Default: `[]` - -### Parameter: `baseTime` - -Do not provide a value! This date value is used to generate a registration token. - -- Required: No -- Type: string -- Default: `[utcNow('u')]` - - -## Outputs - -| Output | Type | Description | -| :-- | :-- | :-- | -| `location` | string | The location the resource was deployed into. | -| `name` | string | The name of the VM. | -| `resourceGroupName` | string | The name of the resource group the VM was created in. | -| `resourceId` | string | The resource ID of the VM. | -| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. | - -## Cross-referenced modules - -This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). - -| Reference | Type | -| :-- | :-- | -| `br/public:avm/res/network/network-interface:0.2.2` | Remote reference | -| `br/public:avm/res/network/public-ip-address:0.2.1` | Remote reference | From 72a248cc41aef12706e1ba1731553f429cd49749 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Wed, 10 Jan 2024 14:22:17 +0100 Subject: [PATCH 34/35] Regenerated all docs --- avm/res/compute/virtual-machine/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/avm/res/compute/virtual-machine/README.md b/avm/res/compute/virtual-machine/README.md index 54974f09ce..0d9dfbd7e4 100644 --- a/avm/res/compute/virtual-machine/README.md +++ b/avm/res/compute/virtual-machine/README.md @@ -2621,7 +2621,12 @@ Do not provide a value! This date value is used to generate a registration token ## Cross-referenced modules -_None_ +This section gives you an overview of all local-referenced module files (i.e., other CARML modules that are referenced in this module) and all remote-referenced files (i.e., Bicep modules that are referenced from a Bicep Registry or Template Specs). + +| Reference | Type | +| :-- | :-- | +| `br/public:avm/res/network/network-interface:0.2.2` | Remote reference | +| `br/public:avm/res/network/public-ip-address:0.2.1` | Remote reference | ## Data Collection From ba225d1c515e0581f92ece07f578c1d426f93fe6 Mon Sep 17 00:00:00 2001 From: AlexanderSehr Date: Fri, 12 Jan 2024 21:20:57 +0100 Subject: [PATCH 35/35] Removed orphaned flag --- avm/res/compute/proximity-placement-group/ORPHANED.md | 4 ---- avm/res/compute/proximity-placement-group/README.md | 5 ----- 2 files changed, 9 deletions(-) delete mode 100644 avm/res/compute/proximity-placement-group/ORPHANED.md diff --git a/avm/res/compute/proximity-placement-group/ORPHANED.md b/avm/res/compute/proximity-placement-group/ORPHANED.md deleted file mode 100644 index ef8fa911d2..0000000000 --- a/avm/res/compute/proximity-placement-group/ORPHANED.md +++ /dev/null @@ -1,4 +0,0 @@ -⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ - -- Only security and bug fixes are being handled by the AVM core team at present. -- If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! \ No newline at end of file diff --git a/avm/res/compute/proximity-placement-group/README.md b/avm/res/compute/proximity-placement-group/README.md index dc027ff2cd..e4ba606bfb 100644 --- a/avm/res/compute/proximity-placement-group/README.md +++ b/avm/res/compute/proximity-placement-group/README.md @@ -1,10 +1,5 @@ # Proximity Placement Groups `[Microsoft.Compute/proximityPlacementGroups]` -> ⚠️THIS MODULE IS CURRENTLY ORPHANED.⚠️ -> -> - Only security and bug fixes are being handled by the AVM core team at present. -> - If interested in becoming the module owner of this orphaned module (must be Microsoft FTE), please look for the related "orphaned module" GitHub issue [here](https://aka.ms/AVM/OrphanedModules)! - This module deploys a Proximity Placement Group. ## Navigation