Public/Install-UnifiedContacts.ps1

function Install-UnifiedContacts {
    [CmdletBinding()]
    Param(
        [Parameter (Mandatory = $true, HelpMessage = "The Url you can copy from your browser when you open the App Service. Format: https://portal.azure.com/#<domain>/resource/subscriptions/<subscriptionId>/resourceGroups/<ressourceGroupName>/providers/Microsoft.Web/sites/<appServiceName>/appServices")][string]$AppServiceAzureUrl,
        [Parameter (Mandatory = $true, HelpMessage = "user name and password of the sql user")][PSCredential]$SqlCredential
    )
    $ErrorActionPreference = "Stop"

    Import-Module Az.Resources
    try {
        $ResourceGroup = (($AppServiceAzureUrl -Split "resourceGroups/")[1] -Split "/")[0]
        $SubscriptionId = (($AppServiceAzureUrl -Split "subscriptions/")[1] -Split "/")[0]
        $AppServiceName = (($AppServiceAzureUrl -Split "sites/")[1] -Split "/")[0]

        Write-Host "ResourceGroup1: $ResourceGroup`nSubscriptionId: $SubscriptionId`nAppServiceName: $AppServiceName"
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Get Web App Information" -PercentComplete 5
        try {
            $context = Get-AzContext
        }
        catch {
            #fall through
        }
        if (!$context -or ($context.Subscription.Id -notlike $SubscriptionId)) {
            Connect-AzAccount -Subscription $SubscriptionId -UseDeviceAuthentication | Out-Null
        }
        #refresh Context
        $context = Get-AzContext
        $User = (az account show --query user.name --output tsv)
        $TenantId = $context.Tenant.Id
        $appService = Get-AzWebApp -ResourceGroupName  $ResourceGroup -Name $AppServiceName 
        $redirectUri = "https://$($appService.EnabledHostNames[0])"
        
        if ($appservice.EnabledHostNames.Count -gt 2) {
            $i = 0
            while ($i -lt $appservice.EnabledHostNames.Count) {
                Write-Host "[$i] $($appservice.EnabledHostNames[$i])" 
                $i++
            }
            $redirectUriNumber = Read-Host -Prompt "Please enter the number of your custom domain" 
            do {
                $redirectUri = "https://$($appService.EnabledHostNames[$redirectUriNumber])"
            }while (-not ($redirectUriNumber -le $appservice.EnabledHostNames.Count -and $redirectUriNumber -ge 0))
        }

        Write-Progress -Activity "Deployment Unified Contacts" -Status "Create Admin Page App registration" -PercentComplete 10

        $appRegAdminPage = New-AppRegistration -AppRegistrationName ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "AppRegistrationNameAdminPage" }).value -RedirectUri @($redirectUri) -AvailableToOtherTenants $false
        Update-AppRegistration -App $appRegAdminPage -PermissionScopeValue "AdminPage.ReadWrite.All" -Permissions @("a154be20-db9c-4678-8ab7-66f6cc099a59", "c79f8feb-a9db-4090-85f9-90d820caa0eb", "1ca167d5-1655-44a1-8adf-1414072e1ef9") -AdminConsentDisplayName "AdminPage.ReadWrite.All" -AdminConsentDescription "Allows to access and use the UnifiedContacts Admin page" -ApplicationIdUri "api://$($appRegAdminPage.AppId)" -RequestedAccessTokenVersion 1
    
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Create Teams App registration" -PercentComplete 20
    
        $appRegTeams = New-AppRegistration -appRegistrationName ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "AppRegistrationNameTeamsApp" }).value -redirectUri @($redirectUri) -AvailableToOtherTenants $true
        Update-AppRegistration -App $appRegTeams -PermissionScopeValue "access_as_user" -Permissions @("e1fe6dd8-ba31-4d61-89e7-88639da4683d", "242b9d9e-ed24-4d09-9a52-f43769beb9d4", "9c7a330d-35b3-4aa1-963d-cb2b9f927841", "08432d1b-5911-483c-86df-7980af5cdee0", "205e70e5-aba6-4c52-a976-6d2d46c48043", "a154be20-db9c-4678-8ab7-66f6cc099a59") -AdminConsentDisplayName "access_as_user" -AdminConsentDescription "Default access" -ApplicationIdUri "api://$($appService.EnabledHostNames[0])/$($appRegTeams.AppId)" -RequestedAccessTokenVersion 2

        Start-Sleep -Seconds 10
        #Refresh appReg Object
        $appRegTeams = Get-AzADApplication -ObjectId $appRegTeams.Id
        Set-TeamsAsAuthorizedClientApplication -App $appRegTeams
    
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Create App secrets" -PercentComplete 30

        $appSecretAdminPage = New-AppSecret -ObjectId $appRegAdminPage.Id -SecretName "main"
        $appSecretTeamsApp = New-AppSecret -ObjectId $appRegTeams.Id -SecretName "main"
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Set SQL Server Firewall Rule" -PercentComplete 40

        New-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroup -ServerName ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "SQLServer" }).value -AllowAllAzureIPs | Out-Null

        Write-Progress -Activity "Deployment Unified Contacts" -Status "Set Key Vault User Permissions" -PercentComplete 50

        $VaultName = ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "KeyVaultName" }).value
        Set-AzKeyVaultAccessPolicy -VaultName $VaultName -UserPrincipalName $User -PermissionsToSecrets get, set, delete | Out-Null
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Set Key Vault Secrets" -PercentComplete 60
     
        New-KeyVaultSecret -SecretValue $appRegAdminPage.AppId  -SecretName "AuthSettings--AdminPageClientId" -VaultName $VaultName | Out-Null
        New-KeyVaultSecret -SecretValue $TenantId  -SecretName "AuthSettings--AdminPageTenantId" -VaultName $VaultName | Out-Null
        New-KeyVaultSecret -SecretValue $appSecretAdminPage  -SecretName "AuthSettings--AdminPageClientSecret" -VaultName $VaultName | Out-Null

        New-KeyVaultSecret -SecretValue $appRegTeams.AppId  -SecretName "AuthSettings--ClientId" -VaultName $VaultName | Out-Null
        New-KeyVaultSecret -SecretValue $TenantId  -SecretName "AuthSettings--TenantId" -VaultName $VaultName | Out-Null
        New-KeyVaultSecret -SecretValue $appSecretTeamsApp  -SecretName "AuthSettings--ClientSecret" -VaultName $VaultName | Out-Null

        New-KeyVaultSecret -SecretValue "Server=tcp:$(($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "SQLServer" }).value).database.windows.net,1433;Initial Catalog=$(($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "SQLDatabase" }).value);Persist Security Info=False;User ID=$($SqlCredential.UserName);password='$($SqlCredential.GetNetworkCredential().Password)';MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" -SecretName "AuthSettings--DatabaseConnectionString" -VaultName $VaultName | Out-Null
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Copy Binaries to storage Account" -PercentComplete 75
    
        $me = Get-AzADUser -UserPrincipalName $User
        $storageAccountName = ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "StorageAccountName" }).value 
        New-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor" | Out-Null
    
        Copy-Binaries -Destination $storageAccountName
        Write-Progress -Activity "Deployment Unified Contacts" -Status "Restart Web Apps" -PercentComplete 90

    ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "WEBSITE_RUN_FROM_PACKAGE" }).value = "https://$(($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "AppSettings__BlobStorageUrl" }).value)/unified-contacts/binaries.zip"
        $settings = @{}
        foreach ($appsetting in $appService.SiteConfig.AppSettings) {
            $settings.add($appsetting.Name, $appsetting.Value)
        }
        $concentTeams = "https://login.microsoftonline.com/$TenantId/adminconsent?client_id=$($appRegTeams.AppId)"
        $consentAdminPage = "https://login.microsoftonline.com/$TenantId/adminconsent?client_id=$($appRegAdminPage.AppId)"
        Set-AzWebApp -ResourceGroupName $ResourceGroup -Name $AppServiceName -AppSettings $settings | Out-Null
        Start-Sleep -Seconds 10

        Write-Host "Please grant the Admin Page app registration permission via this link: $consentAdminPage" -ForegroundColor Cyan
        Write-Host "Please grant the Teams app registration permission via this link: $concentTeams" -ForegroundColor Cyan

        $automateGrant = Read-Host -Prompt "Do you want to grant the permissions automatically: [y] yes" 
        if ($automateGrant.ToLower() -like "y") {
            az login 
            az ad app permission admin-consent --id $appRegTeams.Id
            az ad app permission admin-consent  --id $appRegAdminPage.Id
        }
        
        Write-Host "Your Deployment was succesfull. Go to $AppServiceAzureUrl to restart your App Service." -ForegroundColor Green

    }
    catch {
        Write-Host "Your Deployment has failed. Please try to run Install-UnifiedContacts again." -ForegroundColor Red
        #clean up all resources
        if ($appRegAdminPage.Id) {
            Remove-AzADApplication -ObjectId $appRegAdminPage.Id 
        }
        if ($appRegTeams.Id) {
            Remove-AzADApplication -ObjectId $appRegTeams.Id
        }
        if ($VaultName) {
            try {
                Set-AzKeyVaultAccessPolicy -VaultName $VaultName -UserPrincipalName $User -PermissionsToSecrets get, set, delete, list, purge
                Start-Sleep -Seconds 10
                $keyVaultSecrets = Get-AzKeyVaultSecret -VaultName $VaultName
                foreach ($secret in $keyVaultSecrets) {
                    Remove-AzKeyVaultSecret -VaultName $VaultName -Name $secret.Name -Force 
                    Start-Sleep -Seconds 5
                    Remove-AzKeyVaultSecret -VaultName $VaultName -Name $secret.Name -Force -InRemovedState
                }
            }
            catch {
                #fall through
            }
        }
        if ($storageAccountName) {
            $me = Get-AzADUser -UserPrincipalName $User
            Remove-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor"
        }
        if ($appService) {
 ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "WEBSITE_RUN_FROM_PACKAGE" }).value = "https://unifiedcontacts.blob.core.windows.net/unified-contacts-releases/stable/1.4.0-beta.7/ucPublish_1.4.0-beta.7_824b8e82-0fd0-4b7e-b220-bdc90fdf4f69.zip"
            $settings = @{}
            foreach ($appsetting in $appService.SiteConfig.AppSettings) {
                $settings.add($appsetting.Name, $appsetting.Value)
            }
            Set-AzWebApp -ResourceGroupName $ResourceGroup -Name $AppServiceName -AppSettings $settings
       
            $fireWallRule = Get-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroup -ServerName ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "SQLServer" }).value -FirewallRuleName AllowAllAzureIPs
            if ($fireWallRule) { 
                Remove-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroup -ServerName ($appService.SiteConfig.AppSettings | where-object { $_.Name -eq "SQLServer" }).value -FirewallRuleName $fireWallRule.FirewallRuleName | Out-Null
            }
            try {
                Remove-AzRoleAssignment -ObjectId $me.Id -Scope "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroup/providers/Microsoft.Storage/storageAccounts/$storageAccountName/" -RoleDefinitionName "Storage Blob Data Contributor"
            }
            catch {
                #fall through
            }
        }
    }
}