Using a Service Principal for Azure PowerShell Authentication

The Azure PowerShell cmdlets support two authentication techniques: AAD and self-signed X.509 certificates. AAD authentication can be used for both the classic Azure Service Management (ASM) mode and the new Azure Resource Manager (ARM) mode of the Azure cmdlets. Certificate authentication can be used only for ASM mode. Although certificate authentication is the traditional way to authenticate there is no longer any need to use it since AAD authentication works in all modes of Azure PowerShell and provides role-based access control (RBAC) in ARM mode.

There were several presentations at //Build2015 and Microsoft Ignite indicating that, going forward, ARM is central to the consistent management layer for Azure and the Azure Stack. New cmdlets have been added to the Azure cmdlets to support the use of ARM for many Azure resource types - including VMs, Azure Storage and VNETs.

AAD authentication typically makes use of AAD users added either as a co-admin for ASM or to some role for ARM. This identification is normally done in the Production Portal and Preview Portal respectively. However, it is also possible to use a service principal for authentication in ARM mode. David Ebbo has a post showing how to configure a service principal, through the creation of a dummy application, in the Azure Active Directory section of the Production Portal. Max Vaughan has a post showing how to create a service principal using the Azure Active Directory (formerly MSOL) cmdlets. This post builds on these, and shows how to create a service principal and associate it with ARM roles only using PowerShell. Note that there is no portal support for service principals and they are not surfaced into the portal UI. Service principals can be managed through PowerShell.

AAD and Azure Cmdlets

The AAD cmdlets can be downloaded and installed from here. Note that the Microsoft Online Services Sign-In Assistant for IT Professionals must also be installed, and this can be downloaded from the same page. The Azure cmdlets can be downloaded directly from the GitHub release page.

The service principal is added to the AAD tenant using the AAD cmdlets and then given access to ARM mode using the Azure cmdlets. Consequently, the following must be done by a user who is a co-admin for ASM and in the Owner role for ARM. This user must be signed-in to both MSOL and Azure.

The following cmdlet is used to sign-in to Azure:

Add-AzureAccount

The following cmdlet is used to sign-in to MSOL:

Connect-MsolService

If necessary, the following Azure cmdlets can be used to select the desired subscription:

Get-AzureSubscription

Select-AzureSubscription -SubscriptionName "SomeSubscription"

Set-AzureSubscription -SubscriptionName "SomeSubscription " `
-CurrentStorageAccountName "somestorageaccount"

The ARM mode of Azure PowerShell is selected using the following cmdlet:

Switch-AzureMode -Name AzureResourceManager

Service Principal Creation

(This section has been updated to include the -Addresses parameter to New-MsolServicePrincipal)

The following AAD cmdlet is used to add the service principal:

$servicePrincipalName = "https://UniqueName"
$displayName = "UniqueDisplayName"
$addressName = "https://UniqueName"
$strongPassword = "StrongPassword"

$address = New-MsolServicePrincipalAddresses -Address $addressName -AddressType Reply

New-MsolServicePrincipal -ServicePrincipalNames $servicePrincipalName -DisplayName $displayName -Type Password -Value $strongPassword -Addresses $address

This cmdlet provides output like the following:

DisplayName : UniqueDisplayName
ServicePrincipalNames : {https://UniqueName, e604cbbb-5683-4444-9dfb-a39362562f3c}
ObjectId : cb48f083-b3de-4e4a-9978-b5ccacd58a87
AppPrincipalId : e604cbbb-5683-4444-9dfb-a39362562f3c
TrustedForDelegation : False
AccountEnabled : True
Addresses : {Microsoft.Online.Administration.RedirectUri}
KeyType : Password
KeyId : dee98fd3-0ef6-46c6-a40c-28e82c4c9827
StartDate : 5/31/2015 1:22:18 AM
EndDate : 5/31/2016 1:22:18 AM
Usage : Verify

The New-MSolServicePrincipal cmdlets has parameters allowing the StartDate and EndDate to be specified. The Get-MsolServicePrincipal cmdlet can be used to retrieve information on all the service principals configured for the tenant or for a specific service principal. For example:

Get-MsolServicePrincipal -ServicePrincipalName "https://PSTestApp7"

ExtensionData : System.Runtime.Serialization.ExtensionDataObject
AccountEnabled : True
Addresses : {Microsoft.Online.Administration.RedirectUri}
AppPrincipalId : e604cbbb-5683-4444-9dfb-a39362562f3c
DisplayName : PSTestApp7
ObjectId : cb48f083-b3de-4e4a-9978-b5ccacd58a87
ServicePrincipalNames : {e604cbbb-5683-4444-9dfb-a39362562f3c, https://UniqueName}
TrustedForDelegation : False

Azure Role Assignment

The New-AzureRoleAssignment cmdlet is used to assign a service principal to a role. This is done at one of the three supported scopes: subscription, resource group or resource. The role assignment is inherited from subscription through resource group to resource. ARM supports three system roles (Owner, Contributor and Reader) as well as many resource-provider specific roles (Virtual Machine Contributor, Virtual Network Contributor, etc.). The Get-AzureRoleDefinition cmdlet can be used to retrieve the list of roles and their definition as follows:

Get-AzureRoleDefinition

The following assigns the service principal to the Virtual Network Contributor role for the WestUSDemo resource group:

New-AzureRoleAssignment `
-ServicePrincipalName $servicePrincipalName `
-RoleDefinitionName "Virtual Network Contributor" `
-Scope "/subscriptions/27182818-405e-b406-284590452353/resourceGroups/WestUSDemo"

The Get-AzureRoleAssignment is used to retrieve the role assignments for all users and service principals. For example, the following retrieves the role assignments for the specified service principal:

Get-AzureRoleAssignment `
-ServicePrincipalName $servicePrincipalName

ServicePrincipalName : f24663fe-52f4-4d02-a0f9-8a4138b870d9
RoleAssignmentId : /subscriptions/27182818-405e-b406-284590452353/resourceGroups/WestUSDemo/providers/Microsoft.Authorization/roleAssignments/66a4d61a-75ee-4532-8143-ba35c54bda28
DisplayName : TestServicePrincipal
RoleDefinitionName : Virtual Network Contributor
Actions : {Microsoft.ClassicNetwork/virtualNetworks/*, Microsoft.Authorization/*/read, Microsoft.Resources/subscriptions/resources/read, Microsoft.Resources/subscriptions/resourceGroups/read...}
NotActions : {}
Scope : /subscriptions/27182818-405e-b406-284590452353/resourceGroups/WestUSDemo
ObjectId : 2824dc38-f543-4f4b-91a0-93b490141a18

The service principal can be configured as an Azure PowerShell account as follows:

$tenantId = Get-AzureSubscription | `
Where {$_.IsCurrent -eq "True"} | `
Select TenantId

$appPrincipalId = (Get-MsolServicePrincipal -ServicePrincipalName $servicePrincipalName).AppPrincipalId

$secureCredential = `
New-Object System.Management.Automation.PSCredential ($appPrincipalId, $securePassword)

Add-AzureAccount -ServicePrincipal -Tenant $tenantId -Credential $secureCredential

The Get-AzureSubscription, Select-AzureSubscription and Set-AzureSubscription cmdlets can be used as before to specify that the service principal is used as the account going forward.

A complete example of creating a service principal and assigning it to a role is contained in this gist.