Using the Azure PowerShell (Preview) task in an Azure Pipeline


I wanted an excuse to use the 4.* (preview) version of the task so I could take the Az module out for a spin. My goal was to perform the following steps I would normally perform with a browser and mouse in the Azure Portal:

  • Delete Resource Group if it already exists
  • Create Resource Group
  • Create an App Service Plan
  • Create an App Service (Web App)
  • Enable the System Assigned Managed Identity and grant it access to read Secrets from an Azure Key Vault (already deployed)
  • Create an additional Slot named after the release variable $(Release.EnvironmentName) to deploy the web app into.
  • Creating Application Settings used by the .NET Core Web App in the Slot (This can also be done in the Azure App Service Deploy task but I wanted to try it anyways)
  • Restart the App Service (Web App)

If you’ve tried to create resources in Azure using an ARM template, you might appreciate this approach,

Let’s start with the first four items from the above list, the commands I use are all from the Az module which you can find here. I have defined the following variables in my release environment scoped to my environment titled DV:

  • $(ResourceGroup)
  • $(ResourceGroupLocation)
  • $(WebAppName)
  • $(KeyVaultName)
Pipeline Variables - Scoped to an environment
Pipeline Variables – Scoped to an environment
# Delete resource group if it already exists
Get-AzResourceGroup -Name $(ResourceGroup) | Remove-AzResourceGroup -Verbose -Force

# Create a new resource group
New-AzResourceGroup -Name $(ResourceGroup) -Location $(ResourceGroupLocation)

# Create an App Service plan in STANDARD tier (minimum required by deployment slots)
New-AzAppServicePlan -ResourceGroupName $(ResourceGroup) -Name $(WebAppName) -Location $(ResourceGroupLocation) -Tier "S1"

# Create a Web App
New-AzWebApp -ResourceGroupName $(ResourceGroup) -Name $(WebAppName) -Location $(ResourceGroupLocation) -AppServicePlan $(WebAppName)

The next thing I wanted to do was enable the System Assigned Identity on the App Service because my demo .NET Core Web App grabs a secret out of a Key Vault I have deployed in another resource group in the *same* subscription and I do not want to have to maintain the access credentials from within the applications appSettings{environment}.json files.

# Enable managed identity
Set-AzWebApp -AssignIdentity $true -Name $(WebAppName) -ResourceGroupName $(ResourceGroup)

# Grant Permissions to the Key Vault - $KeyValutName
# Get PrincipalId of the Identity
$WebApp = Get-AzWebApp -ResourceGroupName $(ResourceGroup) -Name $(WebAppName)
Set-AzKeyVaultAccessPolicy -BypassObjectIdValidation -VaultName $(KeyVaultName) -ObjectId $WebApp.Identity.PrincipalId -PermissionsToSecrets Get,List

First we enable the Identity in the App Service. This is the Identity blade in the App Service (pictured below). After we do that we get (Get-AzWebApp) the web app so we can retrieve the PrincipalId from the Identity property.

Azure Portal - App Service - Identity Blade
Azure Portal – App Service – Identity Blade

Now we call Set-AzKeyVaultAccessPolicy to grant access to our App Service System Assigned Identity. *NOTE* you will notice I am using –ByPassObjectIdValidation parameter because otherwise the command will fail with the following error during execution of the command:

##[error]Cannot find the Active Directory object ‘***’ in tenant ‘***’. Please make sure that the user or application service principal you are authorizing is registered in the current subscription’s Azure Active directory. The TenantID displayed by the cmdlet ‘Get-AzContext’ is the current subscription’s Azure Active directory.

I am granting access to the secrets with the following parameter PermissionsToSecrets Get, List which is the same as if you were to go to the Access Policies blade in your Azure Key Vault and manually grant them to the Object ID from above.

Azure Key Vault - Access Policies
Azure Key Vault – Access Policies

The remainder of the script creates a slot, add some application settings and then restart the App Service. The name we are giving the slot is from a release variable available during execution of the release.

# Create a deployment slot with the name of the stage
New-AzWebAppSlot -ResourceGroupName $(ResourceGroup) -Name $(WebAppName) -AppServicePlan $(WebAppName) -Slot $(Release.EnvironmentName)

# Configure Settings required by our App
$AppSettings = @{"ASPNETCORE_ENVIRONMENT" = "$(Release.EnvironmentName)";"APPINSIGHTS_INSTRUMENTATIONKEY" = ""}
Set-AzWebAppSlot -Name $(WebAppName) -ResourceGroupName $(ResourceGroup)  -AppSettings $AppSettings -Slot $(Release.EnvironmentName)

# Restart the web app
Restart-AzWebApp -ResourceGroupName $(ResourceGroup) -Name $(WebAppName)

The $AppSettings value which is passed as a parameter to Set-AzWebAppSlot must be a Hashtable which is why is is formatted the way it is above. My Application Insights instrumentation key is blank on purpose for the moment because I have not scripted that portion of the deployment yet (working on it).

The Azure PowerShell script task does the bulk of the work which I no longer have to perform manually. I then have the last two tasks which deploy the Web App to the DV slot and then swap the DV slot with Production (see image below).

Azure Pipeline - Release
Azure Pipeline – Release

Both of the tasks below use the same variables from the release, the reason being is that none of the drop downs will populate with any of your resources (Resource Group, App Service Name and Slot) because they don’t exist yet 🙂

Using variables for Resource Group, App Service Name and Slot
Using variables for Resource Group, App Service Name and Slot

You can see above the Azure App Service Deploy task I use variables for the resources we build in the script task.

If I go online to check my web app, I can see that it has a connection to my Azure Key Vault.

Demo .NET Core Web App; Sample Home page displaying values from appSettings and Azure Key Vault

Happy Azure PowerShelling!

About Wes MacDonald

Wes MacDonald is a DevOps Consultant for LIKE 10 INC., a DevOps Consulting firm providing premium support, guidance and services for Azure, Office 365 and Azure DevOps.

Trackbacks/Pingbacks

  1. Did your application deploy successfully? Use a selenium test in your release pipeline with a Microsoft-hosted agent | Azure DevOps and Visual Studio Awesomeness - July 26, 2019

    […] we need a selenium test to execute against our web application that we deployed, this is quite easy to do. If you want an end-end example you can refer to the […]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: