Azure Active Directory: Creating Applications and SPNs with Powershell

By Chris Dituri

Oct 072016

As many of you know, Azure Active Directory (AAD) is Microsoft’s multi-tenant cloud based directory and identity management service. Like all of Microsoft’s Azure Services, it can be programmatically driven with Powershell. The defacto Powershell module to accomplish AAD automation is the Azure Active Directory v1.0 module, also known as the MSOnline module. While stable and incredibly useful, the module begins to show some gaps when seeking to automate more advanced operations. Read on as we address two of those gaps: Application Objects and Service Principal generation.

THE PROBLEM

After browsing the Azure Active Directory module documentation and using Get-Command to find cmdlets related to Applications and Service Principals, you’ll come to a realization – the Azure Active Directory v1.0 module only offers cmdlets for working with Service Principals.

PS C:\Users\user> Get-Command -Module msonline *application* | select -expand name
Remove-MsolApplicationPassword

PS C:\Users\user> Get-Command -Module msonline *serviceprincipal* | select -expand name
Get-MsolServicePrincipal
Get-MsolServicePrincipalCredential
New-MsolServicePrincipal
New-MsolServicePrincipalAddresses
New-MsolServicePrincipalCredential
Remove-MsolServicePrincipal
Remove-MsolServicePrincipalCredential
Set-MsolServicePrincipal

Now what? Do you give up on creating the 1,000 application objects that – this morning – the pointy-haired boss told you needed to be delivered yesterday? Do you break the bad news to your teammates that new marching orders from above mean youll all be enduring a copy/paste and clicking marathon for the next 48 hours? Never!

THE SOLUTION

To overcome some of the gaps of the original AAD module we can turn to a successor that’s actively being developed by Microsoft and in public preview, affectionately know as Azure AD Preview. The goal of this module is to subsume the original and be promoted and re-branded as the Azure Active Directory v2.0 module. As noted in the v1.0 documentation:

There are two versions of the Azure Active Directory Module for Windows PowerShell available: a General Availability version (v1.0) and a Public Preview Version (v2.0 also known as AzureADPreview). The Public Preview version contains cmdlets that have not yet been released for General Availability.

Now let’s look at installing and working with Powershell’s Azure AD Preview.

Installing the Azure AD Preview Module

To install the preview module launch a Powershell session as Administrator and execute the following:

PS C:\Users\user> Install-Module -Confirm:$false -Force AzureADPreview

 

Logging into Azure Active Directory

Authenticating to Azure Active Directory is both simple and straight-forward. There are only two important things to note when authenticating – the account being used must be an organizational account and granted the Global Admin role. For more information on these two aspects, see the documentation.

PS C:\Users\user> Connect-AzureAD -Credential (Get-Credential) -Confirm:$true

 

Full Code Listing and Overview

The full code listing below contains a drop-in function which can be used for creating Application Objects and their associated Service Principals. In addition to creating the required objects, the function also covers the most basic necessities when creating new Applications:

  • Setting the Application Home Page, Reply Url, and ApplicationId Url
  • Granting Azure Active Directory permission to read and sign-in users
  • Generating a one year client secret

To use simply copy/paste into a running Powershell session and invoke as follows:

PS C:\Users\user> New-AzureADApplicationWithDirectoryPermissions -ApplicationName MyNewApplication -HomePage "http://myapp.domain.com" -ApplicationIdUrls "http://myapp.domain.com" -ReplyUrl "http://myapp.domain.com/myReplyUrl"

#require azureadpreview

function New-AzureADApplicationWithDirectoryPermissions
{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [String]$ApplicationName,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [String]$HomePage,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [String]$ReplyUrl,

        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [String[]]$ApplicationIdUrls
    )

    # isLoggedInToAzure? if not prompt
    # Note: remember to authenticate with an AAD Organization Account
    try {
        Get-AzureRmContext -EA Stop | Out-Null
    } catch {
        Connect-AzureAD -Credential (Get-Credential) -Confirm:$true
    }

    # Create a .NET Generics List of RequiredResourceAccess
    $requiredResources = [System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.RequiredResourceAccess]]::New()

    # Retrive the AAD SPN and AAD Read and Sign-in Permissions info
    $aad_spn = Get-AzureADServicePrincipal -Filter "DisplayName eq 'Microsoft.Azure.ActiveDirectory'"
    $aad_Oauth2_readAndSignInPerm = $aad_spn | select -expand Oauth2Permissions | ? {$_.value -eq "User.Read"}

    # Create ResourceAccess object representing Read and Sign-in Permission
    $aad_readAndSignInPerm = [Microsoft.Open.AzureAD.Model.ResourceAccess]::New()
    $aad_readAndSignInPerm.Id = $aad_Oauth2_readAndSignInPerm.Id
    $aad_readAndSignInPerm.Type = "Scope"

    # Create RequiredResourceAccess object representing Read and Sign-In Permission on AAD
    $aad_ResourceAccess = [Microsoft.Open.AzureAD.Model.RequiredResourceAccess]::New()
    $aad_ResourceAccess.ResourceAppId = $aad_spn.AppId
    $aad_ResourceAccess.ResourceAccess = $aad_readAndSignInPerm

    $requiredResources.Add($aad_ResourceAccess)

    # Create a new AAD Application with AAD Read and Sign-in Permission
    $app = New-AzureADApplication -DisplayName $ApplicationName `
                                  -HomePage $HomePage `
                                  -IdentifierUris $ApplicationIdUrls `
                                  -ReplyUrls $ReplyUrl `
                                  -RequiredResourceAccess $requiredResources

    # Associate a new Service Principal to new Application 
    $spn = New-AzureADServicePrincipal -AppId $app.AppId -Tags @("WindowsAzureActiveDirectoryIntegratedApp")

    # Generate a client secret
    $now = Get-Date
    $nextYear = $now.AddYears(1)
    $passwordCredential = New-AzureADApplicationPasswordCredential -ObjectId $app.ObjectId -StartDate $now -EndDate $nextYear

    # Aggregate and return an PSCustomObject with the results
    $obj = [pscustomobject][ordered]@{
        ApplicationId=$app.ObjectId
        ApplicationName=$ApplicationName
        ClientId=$app.AppId
        ClientSecret=$passwordCredential.Value
        SignOnUrl=$app.HomePage
        AppIdUrl=$app.ApplicationIdUrls
        ReplyUrl=$app.ReplyUrl
    }

    return $obj
}