sovereignApplications/confidential/hrAppWorkload/scripts/hrAppWorkload.ps1 (173 lines of code) (raw):
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
<#
.SYNOPSIS
This PowerShell script serves as the overarching script to deploy the HR Sample App Workload either in its entirety or in a piecemeal manner the below individual modules.
.DESCRIPTION
- Executes the individual modules - hr app sample workload
Prerequisites:
Connect-AzAccount -Subscription %SUBSCRIPTION_ID%
Add-SqlAzureAuthenticationContext -Interactive
#>
using namespace System.Collections
param (
[Parameter(Mandatory = $false, Position = 0)]
[string] $parRootDeploymentLocation = "eastus",
[Parameter(Mandatory = $false, Position = 1)]
[bool] $parInitializeDatabase = $true
)
#reference to common scripts
. "..\..\..\..\common\common.ps1"
# Retry logic parameters (in case of transient errors)
$varMaxTransientErrorRetryAttempts = 3
$varRetryWaitTime = 60
#bicep files
# TODO: Figure out this unusual pathing. Is it a requirement to call this script from a much higher working directory?
$varHrAppWorkload = '.\hrAppWorkload.bicep'
$varHRAppParametersFile = '.\parameters\hrAppWorkload.parameters.json'
<#
.DESCRIPTION
Deploys HR app Azure resources.
#>
function New-AppResourceDeployment {
param(
[Parameter(Mandatory = $True, Position = 0)]
[string] $parDeployingUserObjectId,
[Parameter(Mandatory = $True, Position = 1)]
[string] $parDeployingUserUpn,
[Parameter(Mandatory = $False, Position = 2)]
[bool] $parIsValidation = $False
)
$varDonotRetryErrorCodes = Get-DonotRetryErrorCodes '../../../../common/const/doNotRetryErrorCodes.json'
$varLoopCounter = 0
while ($varLoopCounter -lt $varMaxTransientErrorRetryAttempts) {
try {
Write-Information ">>> Starting deployment of HR App Azure resources." -InformationAction Continue
$varTimestamp = Get-Date -Format FileDateTimeUniversal
$varAppDeployment = $null
$varDeploymentName = "HrApp-$varTimestamp"
if ($parIsValidation) {
$varAppDeployment = Test-AzDeployment `
-Name $varDeploymentName `
-Location $parRootDeploymentLocation `
-TemplateFile $varHrAppWorkload `
-TemplateParameterFile $varHRAppParametersFile `
-parDeployingUserObjectId $parDeployingUserObjectId `
-parDeployingUserUpn $parDeployingUserUpn `
if ($varAppDeployment.Count -gt 0) {
Write-Error $varAppDeployment[0].Message -ErrorAction Stop
}
Write-Information ">>> Successfully validated input parameter file." -InformationAction Continue
}
else {
$varAppDeployment = New-AzDeployment `
-Name $varDeploymentName `
-Location $parRootDeploymentLocation `
-TemplateFile $varHrAppWorkload `
-TemplateParameterFile $varHRAppParametersFile `
-parDeployingUserObjectId $parDeployingUserObjectId `
-parDeployingUserUpn $parDeployingUserUpn `
-WarningAction Ignore `
if (!$varAppDeployment -or $varAppDeployment.ProvisioningState -eq "Failed") {
Write-Error "Error while executing HR App Azure resources deployment." -ErrorAction Stop
}
else {
Write-Information ">>> Successfully deployed HR App Azure resources." -InformationAction Continue
}
}
return $varAppDeployment
}
catch {
$varLoopCounter++
$varException = $_.Exception
$varErrorDetails = $_.ErrorDetails
$varTrace = $_.ScriptStackTrace
if ($null -ne $varException) {
$errorCode = $varAppDeployment[0].Code
}
Write-Error "$varException \n $varErrorDetails \n $varTrace" -ErrorAction Continue
if ($varDonotRetryErrorCodes -notcontains $errorCode -and $varLoopCounter -lt $varMaxTransientErrorRetryAttempts) {
Write-Information ">>> A deployment error occured, see above. The error may be transient. Retrying deployment after waiting for $varRetryWaitTime seconds." -InformationAction Continue
Start-Sleep -Seconds $varRetryWaitTime
}
else {
if ($varLoopCounter -eq $varMaxTransientErrorRetryAttempts) {
Write-Information ">>> Maximum number of retry attempts reached. Cancelling deployment." -InformationAction Continue
}
Write-Error ">>> Error occurred in HR App Workload deployment. Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
}
}
}
}
function Initialize-AppDatabase() {
param(
[Parameter(Mandatory = $True, Position = 0)]
[PSCustomObject] $parResourceDeploymentOutputs
)
$varDeploymentParameters = Get-Content -Path $varHRAppParametersFile | ConvertFrom-Json
$parSqlAdministratorPassword = $varDeploymentParameters.parameters.parSqlAdministratorLoginPassword.value
# Get remaining outputs from deployment result
$varResourceGroupName = $parResourceDeploymentOutputs.outResourceGroupName.value
$varAttestationProviderName = $parResourceDeploymentOutputs.outAttestationProviderName.value
$varSqlServerName = $parResourceDeploymentOutputs.outSqlServerName.value
$varSqlDatabaseName = $parResourceDeploymentOutputs.outSqlDatabaseName.value
$varVmName = $parResourceDeploymentOutputs.outVmName.value
$varCmkUrl = $parResourceDeploymentOutputs.outCmkUrl.value
$parSqlAdministratorLogin = $parResourceDeploymentOutputs.outSqlAdministratorLogin.value
Write-Information ">>> Initializing app database." -InformationAction Continue
# Initiate database population (which due to cmdlet version requirements needs to run under PS5)
$varLoopCounter = 0
while ($varLoopCounter -lt $varMaxTransientErrorRetryAttempts) {
$varLoopCounter++
try {
.\initializeDatabase.ps1 `
-parResourceGroupName $varResourceGroupName `
-parAttestationProviderName $varAttestationProviderName `
-parSqlServerName $varSqlServerName `
-parSqlDatabaseName $varSqlDatabaseName `
-parSqlAdminUser $parSqlAdministratorLogin `
-parSqlAdminPassword $parSqlAdministratorPassword `
-parVmServicePrincipalName $varVmName `
-parColumnMasterKeyUrl $varCmkUrl
return
}
catch {
$varLoopCounter++
$varException = $_.Exception
$varErrorDetails = $_.ErrorDetails
$varTrace = $_.ScriptStackTrace
Write-Error "$varException \n $varErrorDetails \n $varTrace" -ErrorAction Continue
if ($varLoopCounter -eq $varMaxTransientErrorRetryAttempts) {
Write-Information ">>> Maximum number of retry attempts reached. Cancelling deployment." -InformationAction Continue
Write-Error ">>> Error occurred in initializing database deployment. Please try after addressing the error : $varException \n $varErrorDetails \n $varTrace" -ErrorAction Stop
}
}
}
}
# Begin execution
# Preliminaries
$varAzContext = Get-AzContext
$varAzContextUserObjectId = $varAzContext.Account.ExtendedProperties.HomeAccountId.Split('.')[0]
$varAzContextAccountId = $varAzContext.Account.Id
#Check the deployment location
$varAllowedLocations = @("eastus", "westus", "northeurope", "westeurope")
$varAppWorkloadParameters = Get-Content -Path $varHRAppParametersFile | ConvertFrom-Json
$varDeploymentLocation = $varAppWorkloadParameters.parameters.psobject.properties | Where-Object { $_.Name -eq "parDeploymentLocation" }
if ($null -eq $varDeploymentLocation -or $varDeploymentLocation.Value.value -notin $varAllowedLocations) {
Write-Error ">>> parDeploymentLocation in the parameter file can only be eastus or westus or northeurope or westeurope. These are the only locations that support both Azure Confidential Ledger and AMD CVM DCasv5-series." -ErrorAction Stop
}
# Validate the app resource deployment script with the values from parameter file.
New-AppResourceDeployment `
-parDeployingUserObjectId $varAzContextUserObjectId `
-parDeployingUserUpn $varAzContextAccountId `
-parIsValidation $True
Register-Compute
# Create the app resource deployment in Azure and parse the returned object to retrieve outputs
$varAppDeployment = New-AppResourceDeployment `
-parDeployingUserObjectId $varAzContextUserObjectId `
-parDeployingUserUpn $varAzContextAccountId
# Load content into the Azure SQL Database (turning on Always Encrypt)
if ($parInitializeDatabase) {
Initialize-AppDatabase `
-parResourceDeploymentOutputs $varAppDeployment.Outputs
}