-
-
Save tyconsulting/ec73a46113f53c2ad3b59ccaaa7502ce to your computer and use it in GitHub Desktop.
Create a key-based Azure AD Service Principal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 5.0 | |
#Requires -Modules AzureRM.Resources, AzureRM.Profile | |
<# | |
============================================================================ | |
AUTHOR: Tao Yang | |
DATE: 09/10/2017 | |
Version: 1.0 | |
Comment: Create Azure AD Application and key phrase based Service Principal | |
============================================================================ | |
#> | |
[CmdletBinding()] | |
Param ( | |
[Parameter(Mandatory = $true)][PSCredential]$AzureCredential, | |
[Parameter(Mandatory = $true)] | |
[ValidateScript({ | |
try { | |
[System.Guid]::Parse($_) | Out-Null | |
$true | |
} catch { | |
$false | |
} | |
})] | |
[String]$SubscriptionId, | |
[Parameter(Mandatory = $false)][ValidateNotNullOrEmpty()][String]$AADAppName = 'Automation_' + $([GUID]::NewGuid().Tostring()) -replace('-', ''), | |
[Parameter(Mandatory = $false)][ValidateNotNullOrEmpty()][string]$Role = 'Contributor', | |
[Parameter(Mandatory = $false)][int]$PasswordLength = 44 | |
) | |
#region functions | |
Function New-Password | |
{ | |
param( | |
[UInt32][ValidateScript({$_ -ge 8 -and $_ -le 128})] $Length=10, | |
[Switch] $LowerCase=$TRUE, | |
[Switch] $UpperCase=$FALSE, | |
[Switch] $Numbers=$FALSE, | |
[Switch] $Symbols=$FALSE | |
) | |
if (-not ($LowerCase -or $UpperCase -or $Numbers -or $Symbols)) { | |
throw "You must specify one of: -LowerCase -UpperCase -Numbers -Symbols" | |
return $null | |
} | |
# Specifies bitmap values for character sets selected. | |
$CHARSET_LOWER = 1 | |
$CHARSET_UPPER = 2 | |
$CHARSET_NUMBER = 4 | |
$CHARSET_SYMBOL = 8 | |
# Creates character arrays for the different character classes, | |
# based on ASCII character values. | |
$charsLower = 97..122 | foreach-object { [Char] $_ } | |
$charsUpper = 65..90 | foreach-object { [Char] $_ } | |
$charsNumber = 48..57 | foreach-object { [Char] $_ } | |
$charsSymbol = 35,36,42,43,44,45,46,47,58,59,61,63,64, | |
91,92,93,95,123,125,126 | foreach-object { [Char] $_ } | |
# Contains the array of characters to use. | |
$charList = @() | |
# Contains bitmap of the character sets selected. | |
$charSets = 0 | |
if ($LowerCase) { | |
$charList += $charsLower | |
$charSets = $charSets -bor $CHARSET_LOWER | |
} | |
if ($UpperCase) { | |
$charList += $charsUpper | |
$charSets = $charSets -bor $CHARSET_UPPER | |
} | |
if ($Numbers) { | |
$charList += $charsNumber | |
$charSets = $charSets -bor $CHARSET_NUMBER | |
} | |
if ($Symbols) { | |
$charList += $charsSymbol | |
$charSets = $charSets -bor $CHARSET_SYMBOL | |
} | |
# Returns True if the string contains at least one character | |
# from the array, or False otherwise. | |
# Loops until the string contains at least | |
# one character from each character class. | |
do { | |
# No character classes matched yet. | |
$flags = 0 | |
$output = "" | |
# Create output string containing random characters. | |
1..$Length | foreach-object { | |
$output += $charList[(get-random -maximum $charList.Length)] | |
} | |
# Check if character classes match. | |
if ($LowerCase) { | |
foreach ($char in $output.ToCharArray()) {If ($charsLower -contains $char) {$flags = $flags -bor $CHARSET_LOWER; break }} | |
} | |
if ($UpperCase) { | |
foreach ($char in $output.ToCharArray()) {If ($charsUpper -contains $char) {$flags = $flags -bor $CHARSET_UPPER; break }} | |
} | |
if ($Numbers) { | |
foreach ($char in $output.ToCharArray()) {If ($charsNumber -contains $char) {$flags = $flags -bor $CHARSET_NUMBER; break }} | |
} | |
if ($Symbols) { | |
foreach ($char in $output.ToCharArray()) {If ($charsSymbol -contains $char) {$flags = $flags -bor $CHARSET_SYMBOL; break }} | |
} | |
} | |
until ($flags -eq $charSets) | |
# Output the string. | |
$output | |
} | |
#endregion | |
#Login to Azure | |
$null = Add-AzureRmAccount -Credential $AzureCredential -SubscriptionId $SubscriptionId | |
$Context = Get-AzureRmContext | |
$CurrentAccount = $Context.Account.Id | |
$TenantDomainName = $Context.Tenant.Directory | |
$TenantId = $Context.Tenant.Id | |
#Validating role | |
Write-Output '', "Validating AAD role '$Role'..." | |
If (Get-AzureRMRoleDefinition $Role) | |
{ | |
Write-Output " - AAD role '$Role' validated." | |
} else { | |
Write-Error "Azure AD role '$Role' not found. Unable to continue." | |
Exit -1 | |
} | |
#Create AAD App and service principal | |
$ApplicationPassword = New-Password -Length $PasswordLength -LowerCase -UpperCase -Numbers | |
Write-output '', 'Creating Azure AD application...' | |
Write-Output " - Azure AD Application name: '$AADAppName'" | |
$Application = New-AzureRmADApplication -DisplayName $AADAppName -HomePage ("http://$TenantDomainName/$AADAppName") -IdentifierUris ("http://$TenantDomainName/$AADAppName") -Password $ApplicationPassword | |
Write-Output '', 'Creating Azure AD Application Service Principal.' | |
$ApplicationServicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $Application.ApplicationId | |
Write-output " - Assigning the '$Role' role to the application Service Principal. Please wait..." | |
$NewRole = $null | |
$Retries = 0 | |
While ($NewRole -eq $null -and $Retries -le 5) | |
{ | |
# Sleep here for a few seconds to allow the service principal application to become active (should only take a couple of seconds normally) | |
Start-Sleep -Seconds 10 | |
$RoleAssignment = New-AzureRmRoleAssignment -RoleDefinitionName $Role -ServicePrincipalName $Application.ApplicationId -ErrorAction SilentlyContinue | |
Start-Sleep -Seconds 10 | |
$NewRole = Get-AzureRmRoleAssignment -ServicePrincipalName $Application.ApplicationId -ErrorAction SilentlyContinue | |
$Retries++ | |
} | |
Write-Output '', "The Azure AD Application and service principal is created:" | |
Write-Output " - Azure AD Tenant Domain: '$TenantDomainName'" | |
Write-Output " - Azure AD Tenant Id: '$TenantId'" | |
Write-Output " - Application name: '$AADAppName'" | |
Write-Output " - Application Id: '$($Application.ApplicationId)'" | |
Write-Output " - Application password: '$ApplicationPassword'" | |
Write-Output " - Azure Subscription Id: '$SubscriptionId'" | |
Write-Output " - Azure AD Role: '$Role'" | |
Write-Output '', "Done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment