Creating an Azure Service Principal Account

Last updated

Azure Service Principal Accounts Work with the Azure Resource Management (ARM) API only
Azure Service Principal Accounts Are Only Available from Octopus Deploy Version 3.3 Onwards

Prior to Octopus Deploy 3.3, Azure Management Certificate Accounts (previously known simply as "Azure Subscription Accounts") were the only type of Azure Account available.

Azure Management Certificate Accounts are only able to interact with the legacy Azure interface known as the "Azure Service Management API", which is used when Octopus deploys Cloud Services and Azure Web Apps.

To interact with Azure Resource Manager (ARM), like when Octopus deploys a Resource Group Template, you must use an Azure Service Principal Account.

There are two steps to enable your Octopus Server to manage your Azure subscription via a Service Principal:

  1. Create an Azure Active Directory application and service principal (via PowerShell or the Azure Portal)
  2. Allow Octopus to authenticate with Azure using a Service Principal

Step 1: Create an Azure Active Directory Application and Service Principal

The first step is to create an Azure Active Directory (AAD) application and service principal. You will configure your Octopus Server to authenticate using the service principal you create in AAD, which means you can configure finely grained authorization for your Octopus Server. Creating an Azure Active Directory application and service principal can be done either via PowerShell or the Azure Portal.

Option 1: Use PowerShell

You can use the PowerShell script below to create the Service Principal.

This script requires Azure PowerShell 1.0 or greater.

During the script, you will be prompted to authenticate with Azure. The authenticated user must have administrator permissions in the Active Directory in which the Service Principal is being created.

# Obviously, replace the following with your own values
$subscriptionId = "cd21dc34-73dc-4c7d-bd86-041284e0bc45"
$tenantId = "2a681dca-3230-4e01-abcb-b1fd225c0982"
$password = "correct horse battery staple"

# Login to your Azure Subscription
Login-AzureRMAccount
Set-AzureRMContext -SubscriptionId $subscriptionId -TenantId $tenantId

# Create an Octopus Deploy Application in Active Directory
Write-Output "Creating AAD application..."
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$azureAdApplication = New-AzureRmADApplication -DisplayName "Octopus Deploy" -HomePage "http://octopus.com" -IdentifierUris "http://octopus.com" -Password $securePassword
$azureAdApplication | Format-Table

# Create the Service Principal
Write-Output "Creating AAD service principal..."
$servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $azureAdApplication.ApplicationId
$servicePrincipal | Format-Table

# Sleep, to Ensure the Service Principal is Actually Created
Write-Output "Sleeping for 10s to give the service principal a chance to finish creating..."
Start-Sleep -s 10

# Assign the Service Principal the Contributor Role to the Subscription.
# Roles can be Granted at the Resource Group Level if Desired.
Write-Output "Assigning the Contributor role to the service principal..."
New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $azureAdApplication.ApplicationId

# The Application ID (aka Client ID) will be Required When Creating the Account in Octopus Deploy
Write-Output "Client ID: $($azureAdApplication.ApplicationId)"

The values required for the script above are:

Subscription ID: The ID of the Azure subscription the account will interact with.

Password: A secret value created by you. Ensure you record it, as you will need to enter it into Octopus Deploy.

Tenant ID: The ID of the Active Directory tenant. You can find this in the Properties blade of the Azure Active Directory, listed as 'Directory ID'.

Option 2: Use the Azure Portal

Alternatively, you can create a Service Principal via the Azure Portal.

Note on roles: Your Service Principal will need to be assigned the Contributor role in order to deploy.

The Service Principal will default to expiring in 1 year from the time of creation.

Using the PowerShell script in option 1, you can specify the expiry date by adding the -EndDate parameter to the New-AzureRmADApplication command

-EndDate (new-object System.DateTime 2018, 12, 31)

Using option 2, the Azure portal will allow you to select the expiry time when creating the key.

Note on Least Privilege

In the PowerShell example above the service principal is assigned the Contributor role on the subscription. This isn't always the best idea, you might want to apply a principle of least privilege to the access the service principal has. If that is the case then there are a couple of things worth noting.

Firstly, you might want to constrain the service principal to a single resource group, in which case you just need to assign it the Contributor role on the resource group.

Next you might want to get even more granular and constrain the service principal to a single resource, e.g. a Web App. In this case you have to assign the Contributor role on the Web App and also explicitly assign the Reader role on the subscription itself.

The reason behind this is to do with the way Octopus queries for the web app resources in Azure. In order to be able to handle scenarios where ASEs are being used, Octopus first queries the resource groups and then queries for the web apps within each resource group. When the service principal is assigned Contributor on a resource group it seems to implicitly get Reader on the subscription, but this doesn't seem to be the case when Contributor is assigned directly to a web app and you have to assign Reader explicitly.

Step 2: Allow Octopus to Authenticate with Azure using a Service Principal

Navigate to Infrastructure ➜ Accounts and click Add account in the Azure Subscriptions section.

accounts

On the Create New Account page, in the Authentication Method field select Use a Service Principal.

add account

The values for the following fields come from Azure:

Subscription ID:  The ID of the Azure Subscription this account will interact with. In the Azure Portal, this can be found in the properties of the subscription.

AD Client\Application ID:  This is the ID of the application in Azure Active Directory. It is known as ApplicationID in the PowerShell API, and in the new Azure Portal it can be found under the App registrations blade in the Azure Active Directory. In the old Azure Portal it may be listed as 'Client ID'.

AD Tenant ID: The ID of the Active Directory tenant. You can find this in the Properties blade of the Azure Active Directory, listed as 'Directory ID'.

AD Password\Key: The password for the Azure Active Directory application: this is know as 'Password' in the API or 'Key' in the Azure Portal. New keys can be generated in the portal under the Keys blade of the Azure Active Directory application.

Use the Save and test button to confirm the account can interact with Azure.

What is actually tested?
When you click the Save and Test button, Octopus will attempt to use the account credentials to access the Azure Resource Management (ARM) API and list the Resource Groups in that subscription. You may need to whitelist the appropriate IP Addresses for the Azure Data Center you are targeting. See deploying to Azure via a Firewall for more details.

Creating a New Service Principal Credential

If you need to create a new Service Principal Credential, this can also be done either via PowerShell or the Azure Portal.

Step 1: Creating a New AAD Service Principal Credential

Option 1: Use PowerShell

The following PowerShell script will create an additional credential under the existing AAD application

# Obviously, replace the following with your own values
$subscriptionId = "cd21dc34-73dc-4c7d-bd86-041284e0bc45"
$tenantId = "2a681dca-3230-4e01-abcb-b1fd225c0982"
$applicationId = "1d7f3207-0d20-4ff3-bdd2-c6928a5dd3f0"
$password = "correct horse battery staple 2"

# Login to your Azure Subscription
Login-AzureRMAccount
Set-AzureRMContext -SubscriptionId $subscriptionId -TenantId $tenantId

# Get the Azure AD Appliction
Write-Output "Getting the Azure AD Application"
$azureAdApp = Get-AzureRmADApplication -ApplicationId $applicationId
$azureAdApp | Format-Table

Write-Output "Getting the Azure AD Service Principal"
$azureAdServicePrincpal = Get-AzureRmADServicePrincipal -SearchString $azureAdApp.DisplayName
$azureAdServicePrincpal | Format-Table

Write-Output "Creating a new Service Principal Credential"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$servicePrincipalCred = New-AzureRmADSPCredential -ObjectId $azureAdServicePrincipal.Id -EndDate (New-Object System.DateTime 2019,1,31) -Password $securePassword
$servicePrincipalCred | Format-Table

Option 2: Use the Azure Portal

For the Azure Portal steps, create a new Key using the directions here.

Step 2: Updating the Password/Key in the Octopus Azure Subscriptions

Navigate to Environments ➜ Accounts and click on the account you wish to update in the Azure Subscriptions section.

Use the Change button to modify the password or key and enter the password or key from Step 1.

Edit password

Use the Save and test button to confirm the account can interact with Azure.