common/common.ps1 (247 lines of code) (raw):

# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. <# .SYNOPSIS This PowerShell script serves common functions to deploy sample apps and Workload templates. .DESCRIPTION - Executes the individual modules - lighthouse #> using namespace System.Collections param ( $parAttendedLogin = $true ) #variables to support incremental delay for azure resource validation checks (All time in seconds) $varMaxIntervalResourceExistsCheck = 60 $varIntervalMultiplierResourceExistsCheck = 5 <# .Description Login to Azure portal #> function Enter-Login { Write-Information ">>> Initiating a login" -InformationAction Continue Connect-AzAccount } <# .Description Get details of user #> function Get-SignedInUser { $varSignedInUserDetails = Get-AzADUser -SignedIn if (!$varSignedInUserDetails) { Write-Information ">>> No logged in user found." -InformationAction Continue } else { return $varSignedInUserDetails.UserPrincipalName } return $null } <# .Description Confirm the user is owner at the root scope #> function Confirm-UserOwnerPermission { if ($null -ne $varSignedInUser) { Write-Information "`n>>> Checking the owner permissions for user: $varSignedInUser at '/' scope" -InformationAction Continue $varRetrieveOwnerPermissions = Get-AzRoleAssignment ` -SignInName $varSignedInUser ` -Scope "/" ` -RoleDefinitionName "Owner" if ($varRetrieveOwnerPermissions.RoleDefinitionName -ne "Owner") { Write-Information "Signed in user: $varSignedInUser does not have owner permission to the root '/' scope." -InformationAction Continue return $false } else { Write-Information "Signed in user: $varSignedInUser has owner permissions at the root '/' scope." -InformationAction Continue } return $true } else { Write-Error "Logged in user details are empty." -ErrorAction Stop } } function Set-UserOwnerPermission { Write-Host ">>> Assigning user with Owner permissions." # Assign "Owner" role to the signed-in user at the root scope "/" New-AzRoleAssignment ` -SignInName $varSignedInUser ` -Scope "/" ` -RoleDefinitionName "Owner" } function Invoke-UserPermissionsConfirmation { param($parPermissionType) Write-Host "`n>>> Confirming user's permissions. This might trigger an auto log out and require the user to login back in a few times" $varWaitTime = 10 $varLoopCounter = 0 while ($varTotalWaitTime -lt $varMaxWaitTimeResourceExistsCheck -and $varUserPermissions -eq $false) { try { # Log out to refresh the session Get-AzContext | Remove-AzContext -Confirm:$false Connect-AzAccount # check owner permissions of the user $varUserPermissions = Confirm-UserOwnerPermission if ($varUserPermissions -ne $true) { Write-Host ">>> Checking the permissions after waiting for $varWaitTime secs. Please ensure that you are logged into the appropriate tenant and did not log in to a different tenant during the script execution." $varLoopCounter++ $varWaitTime = New-IncrementalDelay $varWaitTime $varLoopCounter $varTotalWaitTime += $varWaitTime Start-Sleep -Seconds $varWaitTime } } catch { $_.Exception Write-Host ">>> Retrying after waiting for $varWaitTime secs. To stop the retry press Ctrl+C." $varLoopCounter++ $varWaitTime = New-IncrementalDelay $varWaitTime $varLoopCounter $varTotalWaitTime += $varWaitTime Start-Sleep -Seconds $varWaitTime } } } <# .Description Caclulates and returns the number of seconds to wait #> function New-IncrementalDelay { param($parDelay, $parDelayIterator) $parDelay = $parDelay + ($parDelayIterator * $varIntervalMultiplierResourceExistsCheck) if ($parDelay -ge $varMaxIntervalResourceExistsCheck) { $parDelay = $varMaxIntervalResourceExistsCheck } return $parDelay } <# .Description Confirm parameters #> function Confirm-Parameters($parParameters) { $varMissingParameters = New-Object Collections.Generic.List[String] $varArrayParameters = @("parAllowedLocations", "parAllowedLocationsForConfidentialComputing", "parPolicyDefinitionReferenceIds") Foreach ($varParameter in $parParameters) { if ($varParameter -in $varArrayParameters -and $varParameters.$varParameter.value.count -eq 0) { if (!$parAttendedLogin) { $varMissingParameters.add($varParameter) } else { [string[]] $varArray = @() $varArray = Read-Host "Please enter the list of $varParameter with a comma between each" if ($varArray[0] -eq "") { Write-Error "$varParameter value not found" -ErrorAction Stop } $varParameters.$varParameter.value = $varArray.Split(',') } } elseif (($null -eq $varParameters.$varParameter.value) -or [string]::IsNullOrEmpty($varParameters.$varParameter.value) -or ($varParameters.$varParameter.value -eq "{}")) { $varParameters.$varParameter.value = $null if (!$parAttendedLogin) { $varMissingParameters.add($varParameter) } else { $varParameters.$varParameter.value = $(Read-Host -prompt "Please provide the value for $varParameter") if ($varParameters.$varParameter.value -eq "") { Write-Error "$varParameter value not found" -ErrorAction Stop } } } elseif ($varParameters.$varParameter.value.count -gt 1) { $varValue = $varParameters.$varParameter.value if ($varValue -is [array]) { foreach ($varElement in $varValue) { $varResult = Confirm-ObjectType($varElement) if ($varResult -eq $false) { $varMissingParameters.add($varParameter) } } } elseif ($varValue -is [object]) { $varResult = Confirm-ObjectType($varValue) if ($varResult -eq $false) { $varMissingParameters.add($varParameter) } } elseif (($null -eq $varValue) -or [string]::IsNullOrEmpty($varValue) -or ($varValue -eq "{}")) { $varParameters.$varParameter.value = $null return $false } } } if ($varMissingParameters.count -gt 0) { Write-Error "Following parameters are missing : $varMissingParameters" -ErrorAction Stop } $varTenantId = (Get-AzTenant).Id if ($varTenantId -eq $varParameters.parConfidentialVirtualMachineManagementTenantId.value ) { Write-Error "The value of parameter named parConfidentialVirtualMachineManagementTenantId should not be the same as the tenant id $varTenantId where the ConfidentialVirtualMachine script is being deployed. Please use different tenant id for the parConfidentialVirtualMachineManagementTenantId." -ErrorAction Stop } } <# .Description Checks the required Object type parameters are passed based on the deployment. #> function Confirm-ObjectType($parParameter) { if (($null -eq $parParameter)) { return $false } $varMembers = $parParameter.PSObject.Properties | Select-Object Name, Value foreach ($varMember in $varMembers) { if (($null -eq $varMember.value) -or [string]::IsNullOrEmpty($varMember.value) -or ($varMember.value -eq "")) { return $false } } return $true } <# .Description Register Microsoft.Compute namespace. #> function Register-Compute { Write-Information ">>> Registering EncryptionAtHost feature. This may take up to 30 minutes." -InformationAction Continue Register-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute" while ((Get-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute").RegistrationState -ne "Registered") { Write-Information ">>> Waiting on feature registration to complete, checking again in $varRetryWaitTime seconds." -InformationAction Continue Start-Sleep -Seconds $varRetryWaitTime } Write-Information ">>> EncryptionAtHost feature registered." -InformationAction Continue } <# .Description Register resource provider. #> function Register-ResourceProvider { param($varProviderNamespace) $varResourceProvider = $null $varLoopCounter = 0 $varJob = Register-AzResourceProvider -ProviderNamespace $varProviderNamespace -AsJob $varJob | Wait-Job > $null $varResourceProvider = Get-AzResourceProvider -ProviderNamespace $varProviderNamespace while ($null -eq $varResourceProvider -and $varLoopCounter -lt $varMaxRetryAttemptTransientErrorRetry) { Start-Sleep -Seconds $varRetryWaitTimeTransientErrorRetry $varResourceProvider = Get-AzResourceProvider -ProviderNamespace $varProviderNamespace $varLoopCounter++ } } <# .Description Checks Prerequisites for the deployment. #> function Confirm-Prerequisites { param( [int]$parConfirmAZResourceGraphVersion = 0 ) Write-Information ">>> Checking Prerequisites for the deployment" -InformationAction Continue $varConfirmPrerequisites = '..\..\..\common\confirm-prerequisites.ps1' & $varConfirmPrerequisites -parAttendedLogin $parAttendedLogin -parConfirmAZResourceGraphVersion $parConfirmAZResourceGraphVersion -ErrorAction Stop Write-Information ">>> Checking Prerequisites is complete." -InformationAction Continue return } <# .Description Load all the Do not retry error codes from the json file in a hashtable #> function Get-DonotRetryErrorCodes { param ($parFilePath) $varList = New-Object Collections.Generic.List[String] $varFile = Get-Content -Path $parFilePath | ConvertFrom-Json $varFile.errorCodes | ForEach-Object { $varList.add($_.code) } return $varList }