Skip to content

Instantly share code, notes, and snippets.

@bjh1977
Last active October 25, 2020 05:33
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bjh1977/0953b96e7148d6a845f5d331cb7206a5 to your computer and use it in GitHub Desktop.
Save bjh1977/0953b96e7148d6a845f5d331cb7206a5 to your computer and use it in GitHub Desktop.
Create AAD Application, Azure Key Vault, Azure Key Vault Key, Rights to Vault from Application (created for use with Extensible Key Management Using Azure Key Vault (SQL Server))
param (
[string]$Version = $( Read-Host "Input version" ),
[string]$DomainName = $( Read-Host "Input domain name" ),
[string]$ApplicationName = $( Read-Host "Input application name" )
)
$ApplicationURI = $("https://$DomainName/$ApplicationName")
#--------------------------------------------------------------------------------------
# to create 256 bit AES key
# FROM: https://gist.github.com/ctigeek/2a56648b923d198a6e60
function Create-AesManagedObject($key, $IV) {
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
if ($IV) {
if ($IV.getType().Name -eq "String") {
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
}
else {
$aesManaged.IV = $IV
}
}
if ($key) {
if ($key.getType().Name -eq "String") {
$aesManaged.Key = [System.Convert]::FromBase64String($key)
}
else {
$aesManaged.Key = $key
}
}
$aesManaged
}
function Create-AesKey() {
$aesManaged = Create-AesManagedObject
$aesManaged.GenerateKey()
[System.Convert]::ToBase64String($aesManaged.Key)
}
#--------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------
#
#This function is used to get the authentication token.
#
#FROM: http://stackoverflow.com/questions/31684821/how-to-add-application-to-azure-ad-programmatically/39136456#39136456
function GetAuthToken
{
param
(
[Parameter(Mandatory=$true)]
$TenantName
)
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceAppIdURI = "https://graph.windows.net"
$authority = "https://login.windows.net/$TenantName"
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
$authResult = $authContext.AcquireToken($resourceAppIdURI, $clientId,$redirectUri, "Auto")
return $authResult
}
#
#You can then submit a POST request to the Azure Active Directory Graph API in order to create your application. However there is a little setup required...
#
# The name of this AAD instance
$global:tenant = $DomainName
$global:aadSecretGuid = New-Guid
$global:aadDisplayName = $ApplicationName
$global:aadIdentifierUris = @($ApplicationURI)
#BH: Not using this now. Using function "Create-AesKey" instead..
#$guidBytes = [System.Text.Encoding]::UTF8.GetBytes($global:aadSecretGuid)
$global:aadSecretKey = Create-AesKey
$global:aadSecret = @{
'endDate'=[DateTime]::UtcNow.AddDays(365).ToString('u').Replace(' ', 'T');
'keyId'=$global:aadSecretGuid;
'startDate'=[DateTime]::UtcNow.AddDays(-1).ToString('u').Replace(' ', 'T');
'value'=$global:aadSecretKey
}
#Save the key to a file
$SecretFile = $("$SecretFilePath\$($ApplicationName)_Secret.key")
$global:aadSecretKey | out-file $SecretFile
Write-Host $("----- Application Key is $global:aadSecretKey")
Write-Host $("----- Application Key Value saved to file $SecretFile")
# ADAL JSON token - necessary for making requests to Graph API
$global:token = GetAuthToken -TenantName $global:tenant
# REST API header with auth token
$global:authHeader = @{
'Content-Type'='application/json';
'Authorization'=$global:token.CreateAuthorizationHeader()
}
#--------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------
#
#Now you can hit the Graph API, and create the AAD application
#NOTE:
# I modifed the original code taken from http://stackoverflow.com/questions/31684821/how-to-add-application-to-azure-ad-programmatically/39136456#39136456
# so that the "PasswordCredentials" are suplpied rather than "KeyCredentials". Having checked the manifest of an application and key
# created manually in the portal, this is what needs to be provded to achive the same thing here)
#
$resource = "applications"
$payload = @{
'displayName'=$global:aadDisplayName;
'homepage'= $ApplicationURI;
'identifierUris'= $global:aadIdentifierUris;
'passwordCredentials'=@($global:aadSecret)
}
$payload = ConvertTo-Json -InputObject $payload
$uri = "https://graph.windows.net/$($global:tenant)/$($resource)?api-version=1.6"
Write-Host $("----- Calling Graph REST API to create application $ApplicationName")
$result = (Invoke-RestMethod -Uri $uri -Headers $global:authHeader -Body $payload -Method POST -Verbose).value
#--------------------------------------------------------------------------------------
Get-AzureRmADApplication -DisplayNameStartWith $ApplicationName | Select-Object -ExpandProperty 'ApplicationId' | Out-File $SecretFile -Append
cls
$Version = '001'
$DomainName = 'xxxxx.onmicrosoft.com'
$ApplicationNameSQLAdmin = $("SQLServerSA$version-app")
$ApplicationNameSQLDB = $("SQLServerAPP$version-app")
$SecretFilePath = "C:\xxxxxxx\GeneratedKeys"
$SubscriptionName = 'Pay-As-You-Go'
$ApplicationURI = $("https://$domainName/$applicationName")
$KeyVaultResourceGroupName = $("SQLServerKeyVault$version-rg")
$KeyVaultName = $("SQLServer$version-kv")
$KeyVaultKeyName = $("SQLServer$version-kvk")
$Location = 'West Europe'
$SKU = 'premium'
$KeyVaultDestination = 'HSM' #'software' or 'HSM'
$CreateAADApplicationScript = 'CreateAADApplication.ps1'
$CreateKeyVaultScript = 'CreateKeyVault.ps1'
$CreateKeyVaultKeyScript = 'CreateKeyVaultKey.ps1'
$AssignAADAppRightsToKeyVaultScript = 'CreateKeyVaultRightsToAADApplication.ps1'
$executingScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
$AADAppCreationFullPath = Join-Path $executingScriptDirectory $CreateAADApplicationScript
$KeyVaultCreationFullPath = Join-Path $executingScriptDirectory $CreateKeyVaultScript
$KeyVaultKeyCreationFullPath = Join-Path $executingScriptDirectory $CreateKeyVaultKeyScript
$AADAppRightsToVaultCreationFullPath = Join-Path $executingScriptDirectory $AssignAADAppRightsToKeyVaultScript
#------------------------------------------------------------------------
#Create SQL Admin Service Principal
Write-Host "Creating SQL Admin AAD Service Princpal..."
$argumentList = @{"Version"="$Version";
"DomainName"="$DomainName";
"ApplicationName"="$ApplicationNameSQLAdmin"}
& $AADAppCreationFullPath @argumentList
#------------------------------------------------------------------------
#Create SQL App DB Service Principal
Write-Host "Creating SQL App DB AAD Service Princpal..."
$argumentList = @{"Version"="$Version";
"DomainName"="$DomainName";
"ApplicationName"="$ApplicationNameSQLDB"}
& $AADAppCreationFullPath @argumentList
#------------------------------------------------------------------------
#Create Key Vault
Write-Host "Creating Key Vault..."
$argumentList = @{"Version"="$Version";
"SubscriptionName"="$SubscriptionName";
"KeyVaultResourceGroupName"="$KeyVaultResourceGroupName"
"KeyVaultName"="$KeyVaultName"
"Location"="$Location"
"SKU"="$SKU"
"KeyVaultDestination"="$KeyVaultDestination"}
& $KeyVaultCreationFullPath @argumentList
#------------------------------------------------------------------------
#Create Key Vault Key
Write-Host "Creating Key Vault Key..."
$argumentList = @{"KeyVaultName"="$KeyVaultName";
"KeyVaultKeyName"="$KeyVaultKeyName";
"KeyVaultDestination"="$KeyVaultDestination"}
& $KeyVaultKeyCreationFullPath @argumentList
#------------------------------------------------------------------------
#Assign rights to Key Vault for SQL Admin Service Principal
Write-Host "Assigning rights to Key Vault for SQL Admin Service Principal..."
$SAApp = Get-AzureRmADApplication -DisplayNameStartWith $ApplicationNameSQLAdmin
$argumentList = @{"KeyVaultName"="$KeyVaultName";
"ApplicationClientID"="$($SAApp.ApplicationId.ToString())";
"ApplicationObjectID"="$($SAApp.ObjectId.ToString())"}
& $AADAppRightsToVaultCreationFullPath @argumentList
#------------------------------------------------------------------------
#Assign rights to Key Vault for SQL App Service Principal
Write-Host "Assigning rights to Key Vault for SQL App Service Principal..."
$DBApp = Get-AzureRmADApplication -DisplayNameStartWith $ApplicationNameSQLDB
$argumentList = @{"KeyVaultName"="$KeyVaultName";
"ApplicationClientID"="$($DBApp.ApplicationId.ToString())";
"ApplicationObjectID"="$($DBApp.ObjectId.ToString())"}
& $AADAppRightsToVaultCreationFullPath @argumentList
Write-Host "** SCRIPT COMPLETED **"
param (
[string]$Version = $( Read-Host "Input version" ),
[string]$SubscriptionName = $( Read-Host "Input subscription name" ),
[string]$KeyVaultResourceGroupName = $( Read-Host "Input key vault resource group name" ),
[string]$KeyVaultName = $( Read-Host "Input key vault name" ),
[string]$Location = $( Read-Host "Input location" ),
[string]$SKU = $( Read-Host "Input SKU" )
)
#FROM https://azure.microsoft.com/en-gb/documentation/articles/key-vault-get-started/
$SubscriptionID = Get-AzureRmSubscription | where-Object {$_.SubscriptionName -eq $SubscriptionName} | Select-Object -ExpandProperty SubscriptionId
if (!$SubscriptionID)
{
Write-Host "`$SubscriptionID is null!"
exit
}
else
{
Write-Host "`$SubscriptionID is $SubscriptionID"
#Set Subscription
Set-AzureRmContext -SubscriptionId $SubscriptionID
}
#Set Subscription
Set-AzureRmContext -SubscriptionId $SubscriptionID
#Create Resource Group
Write-Host $("----- Creating Resource Group $KeyVaultResourceGroupName at location $Location")
New-AzureRmResourceGroup –Name $KeyVaultResourceGroupName –Location $Location
#Create new Key Vault
Write-Host $("----- Creating Key Vault $KeyVaultName in resource group $KeyVaultResourceGroupName")
New-AzureRmKeyVault -VaultName $KeyVaultName -ResourceGroupName $KeyVaultResourceGroupName -Location $Location -SKU $SKU
#Wait! Make sure Key Vault is properly created
Start-Sleep -Seconds 5
param (
[string]$KeyVaultName = $( Read-Host "Input key vault name" ),
[string]$KeyVaultKeyName = $( Read-Host "Input key vault key name" ),
[string]$KeyVaultDestination = $( Read-Host "Input key vault destination" )
)
#Add new key to the key vault
Write-Host $("----- Creating Key Vault Key $KeyVaultKeyName in Key Vault $KeyVaultName")
$key = Add-AzureKeyVaultKey -VaultName $KeyVaultName -Name $KeyVaultKeyName -Destination $KeyVaultDestination
param (
[string]$KeyVaultName = $( Read-Host "Input key vault name" ),
[string]$ApplicationClientID = $( Read-Host "Input application client ID" ),
[string]$ApplicationObjectID = $( Read-Host "Input application object ID" )
)
#Set Access Policy for vault (assign right to service principle [application])
Write-Host $("----- Setting access policy on Key Vault $KeyVaultName for use by application with id $ApplicationClientID")
Set-AzureRmKeyVaultAccessPolicy -VaultName $KeyVaultName -ObjectID $ApplicationObjectID -PermissionsToKeys all -PassThru
#Register the "service principal" object (as the *local* representation)
New-AzureRmADServicePrincipal -ApplicationId $ApplicationClientID
#Works when app is created from ASM portal (use ServicePrincipalName)
Set-AzureRmKeyVaultAccessPolicy -VaultName $KeyVaultName -ServicePrincipalName $ApplicationClientID -PermissionsToKeys get, list, decrypt,sign, wrapKey, unwrapKey
@bjh1977
Copy link
Author

bjh1977 commented Nov 9, 2016

I now recommend this method for creating the Application and Key: https://www.sabin.io/blog/adding-an-azure-active-directory-application-and-key-using-powershell/

@msilinda
Copy link

msilinda commented Oct 1, 2018

Thank you for posting these. Do you have any examples on how to modify ALL properties of Azure Enterprise Applications that were installed from the Marketplace?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment