deployment/Infrastructure/DeployEnvironment.ps1 (493 lines of code) (raw):

# https://docs.microsoft.com/en-us/cli/azure/reference-index?view=azure-cli-latest param ($product, $environment, $settingsKey) if ($null -eq $product) { $product = read-host -Prompt "Please enter the name of the product (e.g. epmcovi)" } if ($null -eq $environment) { $environment = read-host -Prompt "Please enter the name of the environment (e.g. dev1, tst1, mvp1, ...)" } if ($null -eq $settingsKey){ $settingsKey = "dev" } function DeployEnvironment { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateSet('tst1', 'tst2', 'tst3', 'mvp1', 'dev1')] $nc_Environment, [Parameter(Mandatory = $true)] [ValidateSet('epmcovi', 'homecovi')] # dont use epmcovi on other subsciptions $nc_Product, [Parameter(Mandatory = $true)] $nc_SettingsKey ) $subscriptionId = $(az account show --query id -otsv) Write-Host "Subscription ID: $subscriptionId " -ForegroundColor Green $settings = Get-Settings($nc_SettingsKey) Validate-Settings($settings) # Generating names according to 'Naming convention. Azure Resources.docx) $nc_Instance = "01" $nc_Instance2 = "02" $nc_Region = $settings.region.key $location = $settings.region.name $locationPostgreSQL = $settings.region.name $locationCosmosDB = $settings.region.name $resourceGroupName = "rg-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $storageAccountName = ("sa" + $nc_Region + $nc_Environment + $nc_Product + $nc_Instance + "app").ToLower() $storageAccountWebJobsName = ("sa" + $nc_Region + $nc_Environment + $nc_Product + $nc_Instance2 + "app").ToLower() $keyVaultName = "kv-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $keyVaultCertificateName = "cert-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $appInsightsName = "ai-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $serviceBusNamespaceName = "sbus-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $serviceBusTopicName1 = "contacts" $serviceBusTopicName2 = "notifications" $appServicePlanName = "asp-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $webAppInfectionName = "wa-$nc_Region-$nc_Environment-$nc_Product-infection-$nc_Instance" $webAppIsName = "wa-$nc_Region-$nc_Environment-$nc_Product-is-$nc_Instance" $webAppUserName = "wa-$nc_Region-$nc_Environment-$nc_Product-user-$nc_Instance" $cosmosDBaccountName = ("cassandra-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance").ToLower() $appConfigName = "config-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $postgreSQLServerName = "sql-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $notificationHubsNamespaceName = "nhub-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $notificationHubName = $settings.notificationHub.name $APIManagementServiceName = "api-$nc_Region-$nc_Environment-$nc_Product-$nc_Instance" $functionAppInfectionName = "func-$nc_Region-$nc_Environment-$nc_Product-infection-$nc_Instance" $functionAppNotificationName = "func-$nc_Region-$nc_Environment-$nc_Product-notification-$nc_Instance" # Other variables $clientId = "ed82e190-d95e-403e-bc8f-ca0d932b02c1" $scope = "openid offline_access userApi infectionApi apim" $secret = "secret" ################################################################# # Creating Resource Group ################################################################# Write-Host "Creating Resource Group:" -ForegroundColor Green az group create --location $location --name $resourceGroupName ################################################################# # Deployment App Service Plan - moved to ARM Template Templates/NetCoreApp.json ################################################################# # az appservice plan create --name $appServicePlanName --resource-group $resourceGroupName --sku S1 ################################################################# # Creating Storage Account 1 BLOB ################################################################# Write-Host "Creating Storage Account 1 BLOB:" -ForegroundColor Green az storage account create --name $storageAccountName --resource-group $resourceGroupName --location $location ` --access-tier Hot ` --sku Standard_LRS ` --kind BlobStorage # Creating container in storage account az storage container create --name meetings --account-name $storageAccountName ` --public-access off az storage container create --name recommendations --account-name $storageAccountName ` --public-access blob $storageAccountConnectionString = $(az storage account show-connection-string --name $storageAccountName --resource-group $resourceGroupName --query "connectionString") Write-Host "Storage Account Connection String: $storageAccountConnectionString" -ForegroundColor Cyan az storage blob upload --container-name recommendations --account-name $storageAccountName --auth-mode key --connection-string $storageAccountConnectionString ` --file Configs/recommendations-1.json ` --name 1 ` az storage blob upload --container-name recommendations --account-name $storageAccountName --auth-mode key --connection-string $storageAccountConnectionString ` --file Configs/recommendations-2.json ` --name 2 ` az storage blob upload --container-name recommendations --account-name $storageAccountName --auth-mode key --connection-string $storageAccountConnectionString ` --file Configs/recommendations-3.json ` --name 3 ` az storage blob upload --container-name recommendations --account-name $storageAccountName --auth-mode key --connection-string $storageAccountConnectionString ` --file Configs/recommendations-4.json ` --name 4 ` ################################################################# # Creating Storage Account 2 for Function Apps ################################################################# Write-Host "Creating Storage Account 2 for Function Apps:" -ForegroundColor Green az storage account create --name $storageAccountWebJobsName --resource-group $resourceGroupName --location $location ` --access-tier Hot ` --sku Standard_LRS ` --kind StorageV2 $storageAccountWebJobsConnectionString = $(az storage account show-connection-string --name $storageAccountWebJobsName --resource-group $resourceGroupName --query "connectionString") Write-Host "Storage Account Connection String: $storageAccountWebJobsConnectionString" -ForegroundColor Cyan ################################################################# # Creating Key Vault ################################################################# Write-Host "Creating Key Vault:" -ForegroundColor Green az keyvault create --name $keyVaultName --resource-group $resourceGroupName --location $location ` --enable-soft-delete true # https://github.com/Azure/azure-cli/issues/13247 # Attach self-signed certificate to key vault. Cert will be regenerated every run az keyvault certificate get-default-policy > policy.json az keyvault certificate create --name $keyVaultCertificateName --vault-name $keyVaultName --policy `@policy.json ################################################################# # Creating Service Bus Namespace and Topics ################################################################# Write-Host "Creating Service Bus Namespace and Topics:" -ForegroundColor Green az servicebus namespace create --name $serviceBusNamespaceName --resource-group $resourceGroupName --location $location ` --sku Standard az servicebus topic create --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name $serviceBusTopicName1 az servicebus topic authorization-rule create --topic-name $serviceBusTopicName1 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "Send" ` --rights Send az servicebus topic authorization-rule create --topic-name $serviceBusTopicName1 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "Listen" ` --rights Listen az servicebus topic subscription create --topic-name $serviceBusTopicName1 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "ExposedContacts" az servicebus topic subscription create --topic-name $serviceBusTopicName1 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "Log" az servicebus topic create --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name $serviceBusTopicName2 az servicebus topic authorization-rule create --topic-name $serviceBusTopicName2 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "Send" ` --rights Send az servicebus topic authorization-rule create --topic-name $serviceBusTopicName2 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "Listen" ` --rights Listen az servicebus topic subscription create --topic-name $serviceBusTopicName2 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --name "StatusNotification" $contactsTopicListenConnection = $(az servicebus topic authorization-rule keys list --name Listen --topic-name $serviceBusTopicName1 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --query primaryConnectionString) -replace ";EntityPath=contacts", "" $contactsTopicSendConnection = $(az servicebus topic authorization-rule keys list --name Send --topic-name $serviceBusTopicName1 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --query primaryConnectionString) -replace ";EntityPath=contacts", "" $notificationTopicListenConnection = $(az servicebus topic authorization-rule keys list --name Listen --topic-name $serviceBusTopicName2 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --query primaryConnectionString) -replace ";EntityPath=notifications", "" $notificationTopicSendConnection = $(az servicebus topic authorization-rule keys list --name Send --topic-name $serviceBusTopicName2 --namespace-name $serviceBusNamespaceName --resource-group $resourceGroupName ` --query primaryConnectionString) -replace ";EntityPath=notifications", "" ################################################################# # Creating App Configuration ################################################################# Write-Host "Creating App Configuration:" -ForegroundColor Green az appconfig create --name $appConfigName --sku Standard --resource-group $resourceGroupName --location $location # import backend.json az appconfig kv import --yes --name $appConfigName ` --source file --path Configs/backend.json --format json --separator ":" --prefix "backend:" az appconfig kv import --yes --name $appConfigName ` --source file --path Configs/metadata.json --format json --separator ":" --prefix "metadata:" $appConfigConnectionString = $(az appconfig credential list --name $appConfigName --resource-group $resourceGroupName --query [0]."connectionString") $appConfigUrl = "https://" + $appConfigName + ".azconfig.io" Write-Host "App Configuration Connection String: $appConfigConnectionString" -ForegroundColor Green ################################################################# # Creating Application Insight ################################################################# Write-Host "Creating Application Insight:" -ForegroundColor Green az monitor app-insights component create --resource-group $resourceGroupName --location $location ` --app $appInsightsName ` $appInsightsKey = az resource show --name $appInsightsName --resource-group $resourceGroupName ` --resource-type "Microsoft.Insights/components" ` --query "properties.InstrumentationKey" -o tsv az appconfig kv set --name $appConfigName --yes ` --key ApplicationInsights:InstrumentationKey ` --value $appInsightsKey ################################################################# # Creating CosmosDB account ################################################################# Write-Host "Creating CosmosDB account:" -ForegroundColor Green az cosmosdb create --name $cosmosDBaccountName --resource-group $resourceGroupName ` --locations regionName=$locationCosmosDB failoverPriority=0 isZoneRedundant=False ` --capabilities EnableCassandra # Store password in key vault az keyvault secret set ` --vault-name $keyVaultName ` --name Cassandra-Credentials-Password ` --value $(az cosmosdb keys list --name $cosmosDBaccountName --resource-group $resourceGroupName --query "primaryMasterKey") # Create keyvault reference in app config az appconfig kv set-keyvault --yes ` --name $appConfigName ` --key "Cassandra:Credentials:Password" ` --secret-identifier $(az keyvault secret show --vault-name $keyVaultName --name Cassandra-Credentials-Password --query "id") ` # Store connection in app config az appconfig kv import --yes --name $appConfigName ` --source file --path Configs/cassandra-config.json --format json --separator ":" az appconfig kv set --name $appConfigName --yes ` --key Cassandra:ContactPoints:0 ` --value "$cosmosDBaccountName.cassandra.cosmos.azure.com" az appconfig kv set --name $appConfigName --yes ` --key Cassandra:Credentials:UserName ` --value $cosmosDBaccountName ################################################################# # Creating PostgreSQL server ################################################################# Write-Host "Creating PostgreSQL server:" -ForegroundColor Green $postgreSQLServerAdminPassword = Get-RandomCharacters -length 32 -characters 'ABCDEFGHKLMNOPRSTUVWXYZabcdefghiklmnoprstuvwxyz1234567890-' az postgres up --server-name $postgreSQLServerName --resource-group $resourceGroupName --location $locationPostgreSQL ` --database-name coronaresistance ` --admin-user $settings.postgres.adminName ` --admin-password $postgreSQLServerAdminPassword ` --sku-name $settings.postgres.sku ` --version 10 ` --ssl-enforcement Enabled $postgreSQLServerConnectionString = "Server=$postgreSQLServerName.postgres.database.azure.com;Database=coronaresistance;Port=5432;User Id=$postgreSQLServerAdminName@$postgreSQLServerName;Password=$postgreSQLServerAdminPassword;Ssl Mode=Require;" az keyvault secret set ` --vault-name $keyVaultName ` --name Identity-Connection-String ` --value $postgreSQLServerConnectionString ################################################################# # Creating Net Core Application - Is ################################################################# Write-Host "Creating Net Core Application - Is:" -ForegroundColor Green # Issue with netcore for Azure CLI: az webapp create --name $webAppIsName --resource-group $resourceGroupName --plan $appServicePlanName az deployment group create --resource-group $resourceGroupName ` --name DeployNetCoreApp-Is ` --template-file Templates/NetCoreApp.json ` --parameters webAppName=$webAppIsName AppServicePlanName=$appServicePlanName # scope should be restricted (only App Configuration resource) az webapp identity assign --name $webAppIsName --resource-group $resourceGroupName ` --role "App Configuration Data Reader" ` --scope /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName az keyvault set-policy --name $keyVaultName ` --object-id $(az webapp identity show --name $webAppIsName --resource-group $resourceGroupName --query principalId) ` --secret-permissions get az webapp config appsettings set --name $webAppIsName --resource-group $resourceGroupName ` --settings KeyVault:BaseUrl=$(az keyvault show --name $keyVaultName --query properties.vaultUri) az webapp config appsettings set --name $webAppIsName --resource-group $resourceGroupName ` --settings KeyVault:SecretName=$keyVaultCertificateName # AppConfig setting az webapp config appsettings set --name $webAppIsName --resource-group $resourceGroupName ` --settings AppConfig:BaseUrl=$appConfigUrl az webapp config connection-string set --name $webAppIsName --resource-group $resourceGroupName ` --connection-string-type PostgreSQL ` --settings ConnectionStrings:IdentityConnectionString=$postgreSQLServerConnectionString az webapp config connection-string set --name $webAppIsName --resource-group $resourceGroupName ` --connection-string-type PostgreSQL ` --settings ConnectionStrings:IdentityServerConnectionString=$postgreSQLServerConnectionString az webapp config connection-string set --name $webAppIsName --resource-group $resourceGroupName ` --connection-string-type Custom ` --settings AppConfig=$appConfigConnectionString $webAppIsURL = "https://" + $(az webapp show --name $webAppIsName --resource-group $resourceGroupName --query hostNames[0]) Write-Host "App Service 'IS' Connection String: $webAppIsURL" -ForegroundColor Cyan ################################################################# # Deployment Net Core Application - Infection ################################################################# Write-Host "Creating Net Core Application - Infection:" -ForegroundColor Green az deployment group create --resource-group $resourceGroupName ` --name DeployNetCoreApp-Infection ` --template-file Templates/NetCoreApp.json ` --parameters webAppName=$webAppInfectionName AppServicePlanName=$appServicePlanName # scope should be restricted (only App Configuration resource) az webapp identity assign --name $webAppInfectionName --resource-group $resourceGroupName ` --role "App Configuration Data Reader" ` --scope /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName az keyvault set-policy --name $keyVaultName ` --object-id $(az webapp identity show --name $webAppInfectionName --resource-group $resourceGroupName --query principalId) ` --secret-permissions get # ApiIdentity:Authority setting az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings ApiIdentity:Authority=$webAppIsURL az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings ApiIdentity:ClientId="infectionApi" az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings ApiIdentity:ClientSecret=$secret # AppConfig setting az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings AppConfig=$appConfigConnectionString az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings AppConfig:BaseUrl=$appConfigUrl # Blob:ConnectionString setting az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings Blob:ConnectionString=$storageAccountConnectionString az webapp config appsettings set --name $webAppInfectionName --resource-group $resourceGroupName ` --settings Blob:ContainerName="meetings" ################################################################# # Creating Net Core Application - User ################################################################# Write-Host "Creating Net Core Application - User:" -ForegroundColor Green az deployment group create --resource-group $resourceGroupName ` --name DeployNetCoreApp-User ` --template-file Templates/NetCoreApp.json ` --parameters webAppName=$webAppUserName AppServicePlanName=$appServicePlanName # scope should be restricted (only App Configuration resource) az webapp identity assign --name $webAppUserName --resource-group $resourceGroupName ` --role "App Configuration Data Reader" ` --scope /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName az keyvault set-policy --name $keyVaultName ` --object-id $(az webapp identity show --name $webAppUserName --resource-group $resourceGroupName --query principalId) ` --secret-permissions get az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings ApiIdentity:Authority=$webAppIsURL az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings ApiIdentity:ClientId="userApi" az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings ApiIdentity:ClientSecret=$secret az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings ClientIdentity:Authority=$webAppIsURL az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings ClientIdentity:ClientId=$clientId az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings ClientIdentity:Scope=$scope # AppConfig setting az webapp config appsettings set --name $webAppUserName --resource-group $resourceGroupName ` --settings AppConfig:BaseUrl=$appConfigUrl az webapp config connection-string set --name $webAppUserName --resource-group $resourceGroupName ` --connection-string-type Custom ` --settings AppConfig=$appConfigConnectionString az webapp config connection-string set --name $webAppUserName --resource-group $resourceGroupName ` --connection-string-type PostgreSQL ` --settings ConnectionStrings:IdentityConnectionString=$postgreSQLServerConnectionString ################################################################# # Creating API Management Service ################################################################# Write-Host "Creating API Management Service:" -ForegroundColor Green $blobBaseUrl = "https://" + $storageAccountName + ".blob.core.windows.net" $identityServerBaseUrl = "https://" + $webAppIsName + ".azurewebsites.net" $infectionApiBaseUrl = "https://" + $webAppInfectionName + ".azurewebsites.net" $userApiBaseUrl = "https://" + $webAppUserName + ".azurewebsites.net" az deployment group create --resource-group $resourceGroupName ` --name DeployAPIManagementService ` --template-file Templates/APIManagementService.json ` --parameters ` APIManagementServiceName=$APIManagementServiceName ` publisherEmail=test@epam.com ` publisherName=EPAM ` apiClientId="apim" ` apiClientSecret=$secret ` blobBaseUrl=$blobBaseUrl ` clientId=$clientId ` identityServerBaseUrl=$identityServerBaseUrl ` infectionApiBaseUrl=$infectionApiBaseUrl ` scope=$scope ` userApiBaseUrl=$userApiBaseUrl ################################################################# # Creating Notification Hub ################################################################# Write-Host "Creating Notification Hub Namespace:" -ForegroundColor Green az notification-hub namespace create --resource-group $resourceGroupName --location $location ` --name $notificationHubsNamespaceName ` --sku Free # Delay to avoid messages 'Notification Hub Namespace is not ready or not found" Write-Host "Delay 60 seconds" -ForegroundColor Cyan Start-Sleep -Seconds 60 Write-Host "Creating Notification Hub:" -ForegroundColor Green az notification-hub create --namespace-name $notificationHubsNamespaceName --resource-group $resourceGroupName --location $location ` --name $notificationHubName $Host.UI.RawUI.ForegroundColor = 'White' $notificationHubConnection = $(az notification-hub authorization-rule list-keys --namespace-name $notificationHubsNamespaceName --resource-group $resourceGroupName ` --notification-hub-name $notificationHubName --name DefaultFullSharedAccessSignature --query primaryConnectionString) $Host.UI.RawUI.ForegroundColor = 'White' # Update Google (GCM/FCM) key $googleApiKey = Get-Content -Path $($settings.notificationHub.credentials.googleApiKeyFile) az notification-hub credential gcm update --namespace-name $notificationHubsNamespaceName --resource-group $resourceGroupName ` --notification-hub-name $notificationHubName ` --google-api-key $googleApiKey # Update Apple (APNS) certificate # https://docs.microsoft.com/en-us/cli/azure/ext/notification-hub/notification-hub/credential/apns?view=azure-cli-latest#ext-notification-hub-az-notification-hub-credential-apns-update $certificateKey = Get-Content -Path $($settings.notificationHub.credentials.appleCertificateKeyFile) az notification-hub credential apns update --namespace-name $notificationHubsNamespaceName --resource-group $resourceGroupName ` --notification-hub-name $notificationHubName ` --apns-certificate $($settings.notificationHub.credentials.appleCertificateFile) ` --certificate-key $certificateKey $Host.UI.RawUI.ForegroundColor = 'White' ################################################################# # Creating Function App - Infection ################################################################# Write-Host "Creating Function App - Infection:" -ForegroundColor Green # Checks if function exists. Command 'az functionapp create' is not idempotent $funcExist = $false $funcList = az functionapp list --resource-group $resourceGroupName --query "[].id" | ConvertFrom-JSON foreach ($func in $funcList) { if ($func -like "*/sites/$functionAppInfectionName" ) { $funcExist = $true } } if (!$funcExist) { az functionapp create --resource-group $resourceGroupName --storage-account $storageAccountWebJobsName ` --name $functionAppInfectionName ` --os-type Windows ` --runtime dotnet ` --functions-version 3 ` --plan $appServicePlanName ` --app-insights $appInsightsName } az functionapp update --name $functionAppInfectionName --resource-group $resourceGroupName ` --set httpsOnly=true az functionapp identity assign --name $functionAppInfectionName --resource-group $resourceGroupName ` --role "App Configuration Data Reader" ` --scope /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName az keyvault set-policy --name $keyVaultName ` --object-id $(az functionapp identity show --name $functionAppInfectionName --resource-group $resourceGroupName --query principalId) ` --secret-permissions get # AppConfig setting az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings AppConfig:BaseUrl=$appConfigUrl az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings AppConfig=$appConfigConnectionString az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings AzureWebJobsStorage=$storageAccountWebJobsConnectionString az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings BlobConnection=$storageAccountConnectionString az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings BlobPath="meetings" az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings ContactsTopicListenConnection=$contactsTopicListenConnection az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings ContactsTopicName="contacts" az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings ContactsTopicSendConnection=$contactsTopicSendConnection az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings ExposedContactsSubscription="ExposedContacts" az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings NotificationsTopicName="notifications" az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings NotificationTopicSendConnection=$notificationTopicSendConnection az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings RetryPolicy:MaxRetryCount=3 ################################################################# # Creating Function App - Notification ################################################################# Write-Host "Creating Function App - Notification:" -ForegroundColor Green # Checks if function exists. Command 'az functionapp create' is not idempotent $funcExist = $false $funcList = az functionapp list --resource-group $resourceGroupName --query "[].id" | ConvertFrom-JSON foreach ($func in $funcList) { if ($func -like "*/sites/$functionAppNotificationName" ) { $funcExist = $true } } if (!$funcExist) { az functionapp create --resource-group $resourceGroupName --storage-account $storageAccountWebJobsName ` --name $functionAppNotificationName ` --os-type Windows ` --runtime dotnet ` --functions-version 3 ` --plan $appServicePlanName ` --app-insights $appInsightsName } az functionapp update --name $functionAppInfectionName --resource-group $resourceGroupName ` --set httpsOnly=true az functionapp identity assign --name $functionAppNotificationName --resource-group $resourceGroupName ` --role "App Configuration Data Reader" ` --scope /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName az keyvault set-policy --name $keyVaultName ` --object-id $(az functionapp identity show --name $functionAppNotificationName --resource-group $resourceGroupName --query principalId) ` --secret-permissions get # AppConfig setting az functionapp config appsettings set --name $functionAppNotificationName --resource-group $resourceGroupName ` --settings AppConfig:BaseUrl=$appConfigUrl az functionapp config appsettings set --name $functionAppNotificationName --resource-group $resourceGroupName ` --settings NotificationHub:Connection=$notificationHubConnection az functionapp config appsettings set --name $functionAppNotificationName --resource-group $resourceGroupName ` --settings NotificationHub:Name=$notificationHubName az functionapp config appsettings set --name $functionAppNotificationName --resource-group $resourceGroupName ` --settings NotificationsTopicListenConnection=$notificationTopicListenConnection az functionapp config appsettings set --name $functionAppNotificationName --resource-group $resourceGroupName ` --settings NotificationsTopicName="notifications" az functionapp config appsettings set --name $functionAppNotificationName --resource-group $resourceGroupName ` --settings StatusNotificationSubscription="StatusNotification" az functionapp config appsettings set --name $functionAppInfectionName --resource-group $resourceGroupName ` --settings RetryPolicy:MaxRetryCount=3 } # Get-RandomCharacters function is used to generate password function Get-RandomCharacters($length, $characters) { $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length } $private:ofs="" return [String]$characters[$random] } function Get-Settings($settingsKey) { $settingsFile = "./settings/$settingsKey.psd1" if (Test-Path $settingsFile) { return Import-PowerShellDataFile $settingsFile } else { throw "File '$settingsFile' not found." } } function Validate-Settings($settings) { $fileMap = @{ appleCertificateFile = $settings.notificationHub.credentials.appleCertificateFile appleCertificateKeyFile = $settings.notificationHub.credentials.appleCertificateKeyFile googleApiKeyFile = $settings.notificationHub.credentials.googleApiKeyFile } foreach ($entry in $fileMap.GetEnumerator()) { if (-Not $entry.Value) { throw "$($entry.Name) file is not specified" } if (-Not (Test-Path $entry.Value)) { throw "$($entry.Name) file '$($entry.Value)' does not exists" } } } DeployEnvironment -nc_Environment $environment -nc_Product $product -nc_SettingsKey $settingsKey