Export/New-CustomAzVmss.ps1
# Will be called in VM function Global:New-CustomAzVmss { [CmdletBinding()] <# .SYNOPSIS ... .DESCRIPTION ... #> param( [Parameter(Mandatory = $true)] [string] $ResourceGroupName, [Parameter(Mandatory = $true)] [string] $ResourceLocation, [Parameter(Mandatory = $true)] [string] $Name, [Parameter(Mandatory = $true)] [int] $NoOfInstances, [Parameter(Mandatory = $true)] [string] $BaseImageName, [Parameter(Mandatory = $true)] [string] $VMSize, [Parameter(Mandatory = $true)] [PSCredential] $VMCredentials, [Parameter(Mandatory = $true)] [string] $ComputerNamePrefix, [Parameter(Mandatory = $true)] [string] $NetworkIPConfigName, [Parameter(Mandatory = $true)] [string] $NetworkInterfaceConfigName, [Parameter(Mandatory = $true)] [string] $LoadBalancerName, [Parameter(Mandatory = $true)] [string] $FrontendIpConfigName, [Parameter(Mandatory = $true)] [string] $VirtualNetworkName, [Parameter(Mandatory = $true)] [string] $SubnetName, [Parameter(Mandatory = $false)] [string] $SubnetAddressPrefix, [Parameter(Mandatory = $true)] [switch] $CreatePublicIP, [Parameter(Mandatory = $true)] [string] $BackendAddressPoolName, #[Parameter(Mandatory = $true)] #[string] #$AdminUsername, #[Parameter(Mandatory = $true)] #[string] #$AdminPassword, [Parameter(Mandatory = $true)] [string] $KeyVaultName, [switch] $AsJob ) process { # TODO: Check if credentials should be taken from KeyVault instead of passing them as parameter # TODO: Check if Domain Join can be done with xxx # see: https://docs.microsoft.com/en-us/powershell/module/az.compute/set-azvmssosprofile?view=azps-2.8.0 # https://docs.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-unattendedjoin-identification-joindomain $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -VMScaleSetName $Name -ErrorAction SilentlyContinue if ($VMSS) { Write-CustomHost -Message "Scale Set $Name already exists." return } Write-CustomHost -Message "Creating Scale Set $Name ..." # TODO: Add handling for Subnet-creation (if not existing) $scriptBlock = { # Create Variables in Scope of ScriptBlock for all variables passed in ArgumentList $args[0].GetEnumerator() | ForEach-Object { New-Variable -Name $_.Key -Value $_.Value } #Write-CustomHost -Message "Creating Scale Set $Name..." $VNet = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VirtualNetworkName -ErrorAction SilentlyContinue $VMSSIPCfg = New-AzVmssIPConfig -Name $NetworkIPConfigName -SubnetId $VNet.Subnets[0].Id <# # DomainJoin-extension settings $Settings = @{ "Name" = "bctest.local"; "User" = "bctest.local\$AdminUsername"; "Restart" = "true"; "Options" = 3; #"OUPath" = "OU=TEST,OU=My Computers,DC=yourdomain,DC=onmicrosoft,DC=com" } $ProtectedSettings = @{ "Password" = $AdminPassword } # | Set-AzVmssOSProfile -ComputerNamePrefix $ComputerNamePrefix -AdminUsername $AdminUsername -AdminPassword $AdminPassword ` #> $adminUserName = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminUsername').SecretValueText $adminUserPass = (Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name 'DomainAdminPassword').SecretValueText # TODO: Check if its possible to start with 0 instances and update later # Last time KeyVault assignment failed $NoOfInstances = 0 $domainJoinSettings = Get-DomainJoinExtensionSettings -KeyVaultName $KeyVaultName $VMSS = New-AzVmssConfig -Location $ResourceLocation -SkuCapacity $NoOfInstances -SkuName $VMSize -UpgradePolicyMode "Automatic" -IdentityType SystemAssigned ` | Add-AzVmssNetworkInterfaceConfiguration -Name $NetworkInterfaceConfigName -Primary $True -IPConfiguration $VMSSIPCfg ` | Add-AzVmssExtension -Publisher $domainJoinSettings.Publisher -Type $domainJoinSettings.Type -TypeHandlerVersion $domainJoinSettings.TypeHandlerVersion -Name $domainJoinSettings.Name -Setting $domainJoinSettings.Settings -ProtectedSetting $domainJoinSettings.ProtectedSetting -AutoUpgradeMinorVersion $true ` | Set-AzVmssOSProfile -ComputerNamePrefix $ComputerNamePrefix -AdminUsername $adminUserName -AdminPassword $adminUserPass ` | Set-AzVmssStorageProfile -OsDiskCreateOption 'FromImage' -OsDiskCaching "None" ` -ImageReferenceId (Get-AzImage -ImageName $BaseImageName -ResourceGroupName $resourceGroupName).Id $VMSS = New-AzVmss -ResourceGroupName $ResourceGroupName -Name $Name -VirtualMachineScaleSet $VMSS Write-CustomHost -Message "Done." # TODO: Check if Role "Contributor" is necessary $VMSS = Get-AzVmss -ResourceGroupName $ResourceGroupName -VMScaleSetName $Name $RoleDefinitionName = "Contributor" if (-not(Get-AzRoleAssignment -ObjectId $VMSS.Identity.PrincipalId -ResourceGroupName $ResourceGroupName -RoleDefinitionName $RoleDefinitionName -ErrorAction SilentlyContinue)) { Write-CustomHost -Message "Assigning access role to managed identity of VM Scale Set..." New-AzRoleAssignment -ObjectId $VMSS.Identity.PrincipalId -RoleDefinitionName $RoleDefinitionName -ResourceGroupName $ResourceGroupName | Out-Null Write-CustomHost -Message "Done." } Write-CustomHost -Message "Waiting for 30 seconds, so that the managed identity is available..." Start-Sleep -Seconds 30 Set-KeyVaultPermissionsForScaleSet -ResourceGroupName $ResourceGroupName -KeyVaultName $KeyVaultName -ScaleSetName $Name } # Get all parameters from within this function call and pass to actual ScriptBlock $params = Get-FunctionParameters $MyInvocation if ($AsJob) { Start-Job -ScriptBlock $scriptBlock -InitializationScript { Import-Module SetupD365Environment -Force } -ArgumentList $params } else { Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $params } } } Export-ModuleMember -Function New-CustomAzVmss |