There are certain things to overcome to use Connect-AzureAD from powershell script under azure functions by authenticating with certificate. This article explains how to do it.
Azure functions has been deployed already.
1 Generate Certificate and Service Principal
To run Azure AD powershell commands, we need to connect to Azure AD first. Connect-AzureAD currently supports three methods to connect to Azure AD, refer to Connect-AzureAD
- By credential
- By CertificateThumbprint & ApplicationId
- By AadAccessToken & AccountId
Since we don't want to store cleartext credentials in our azure functions app, the best choice here is to use certificate.
To generate a self-signed certificate and associate it with an AAD applicaiton service principal, we can follow below steps.
NOTE: Please replace
YOUR_APP_NAME with corresponding values.
# Login to Azure AD PowerShell With Admin Account Connect-AzureAD # Create the self signed cert $currentDate = Get-Date $endDate = $currentDate.AddYears(1) $notAfter = $endDate.AddYears(1) $pwd = "YOUR_PASSWORD" $thumb = (New-SelfSignedCertificate -CertStoreLocation cert:\localmachine\my -DnsName YOUR_DNS -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $notAfter).Thumbprint $pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText Export-PfxCertificate -cert "cert:\localmachine\my\$thumb" -FilePath YOUR_PFX_PATH.pfx -Password $pwd # Load the certificate $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("YOUR_PFX_PATH.pfx", $pwd) $keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData()) # Create the Azure Active Directory Application $application = New-AzureADApplication -DisplayName "YOUR_APP_NAME" -IdentifierUris "https://YOUR_APP_NAME" New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "YOUR_PASSWORD" -StartDate $currentDate -EndDate $endDate -Type AsymmetricX509Cert -Usage Verify -Value $keyValue # Create the Service Principal and connect it to the Application $sp = New-AzureADServicePrincipal -AppId $application.AppId # Give the Service Principal Reader access to the current tenant (Get-AzureADDirectoryRole) Add-AzureADDirectoryRoleMember -ObjectId 72f988bf-86f1-41af-91ab-2d7cd011db47 -RefObjectId $sp.ObjectId # Get Tenant Detail $tenant = Get-AzureADTenantDetail # Now you can login to Azure PowerShell with your Service Principal and Certificate Connect-AzureAD -TenantId $tenant.ObjectId -ApplicationId $sp.AppId -CertificateThumbprint $thumb # Output TenantId, AppId and Thumbprint to use in azure function's script Write-Host "TenantId: "$tenant.ObjectId Write-Host "AppId: "$sp.AppId Write-Host "Thumbprint: "$thumb
2 Configure Azure Function to Use Certificate
To use the generated certificate to connect to Azure AD, we need to make the certificate avaiable to Azure functions, from Azure portal
- YOUR_AZURE_FUNCTION->Platform features->SSL, click 'Upload Certificate' to upload the exported .pfx format certificate in Step 1
- YOUR_AZURE_FUNCTION->Platform features->Application settings->Add new settings, add a new setting with name called 'WEBSITE_LOAD_CERTIFICATE' and set its value to thumbprint of generated certificate.
- YOUR_AZURE_FUNCTION->Platform features->Application settings->Platform, change to 64-bit.
- YOUR_AZURE_FUNCTION->Platform features->Deployment credentials, set a credential to be used later with FTP deployment.
3 Copy AzureAD PowerShell Module to Azure Function
Azure functions hosting environment doesn't provide AzureAD powershell module by default, to use AzureAD powershell module, we need to 'INJECT' it into the Azure functions host environment. Basically we need a central place to store AzureAD powershell module and load it from this central place. We will use wwwroot\YOUR_FUNCTION_NAME as the central place.
- First, let's store a copy of AzureAD module from local powershell environment, from a Windows machine, run
Save-Module AzureAD -Repository PSGallery -Path C:\Temp
- A folder named AzureAD will be created under C:\Temp and all AzureAD related files will be downloaded into this folder.
- Now copy AzureAD module to Azure function hosting environment, from YOUR_AZURE_FUNCTION->Platform features-Properties, find ftp URL of 'FTP Host Name'
- from Windows Explorer, access 'FTP Host Name' URL with deployment credential configured preivously in Step 2
- Navigate to site/wwwroot/YOUR_FUNCTION_NAME then copy AzureAD into it
4 Write PowerShell Script from Azure Function to Connect to Azure AD
With the configurations & setups from Step 1, Step 2 and Step 3, we are good to run AzureAD powershell scripts from Azure function now. Here are the steps to create powershell azure functions and call Connect-AzureAD,
From Azure portal, create an Azure powershell function
Then copy/paste below code snippet into it
Write-Output "PowerShell function executing at:$(get-date)"; $FunctionName = 'YOUR_FUNCTION_NAME' $ModuleName = 'AzureAD' # Replace module version with $ModuleVersion = '18.104.22.168' # Your Aad Tenant Id $TenantId = 'YOUR_TENANT_ID' # Your Application Service Principal Id $AppId = 'YOUR_APP_ID' # Your Certificate Thumbprint $Thumbprint = 'YOUR_THUMBPRINT' # Import AzureAD PS module $PSModulePath = "D:\home\site\wwwroot\$FunctionName\$ModuleName\$ModuleVersion\$ModuleName.psd1" Import-module $PSModulePath # Connect to AAD Connect-AzureAD -TenantId $TenantId -ApplicationId $AppId -CertificateThumbprint $Thumbprint Write-Output "PowerShell function executed at:$(get-date)";
- YOUR_FUNCTION_NAME needs to be replaced with real azure function name.
- YOUR_TENANT_ID, YOUR_APP_ID and YOUR_THUMBPRINT needs to be replaced as well, those information can be found from Step 1's output.
- Depends on the exported AzureAD module version, $ModuleVersion need to be changed. To check AzureAD module, check the subfolder under AzureAD folder, the subfolder's name is the module version.
The powershell Azure function should be ready now, click 'Run' button, the output should be like below
2018-05-30T10:03:59 Welcome, you are now connected to log-streaming service. 2018-05-30T10:04:22.488 [Info] Function started (Id=386cd8a7-4e0b-4120-a669-353b28527ab3) 2018-05-30T10:04:22.581 [Info] PowerShell function executing at:05/30/2018 10:04:22 2018-05-30T10:04:23.675 [Info] Microsoft.Open.Azure.AD.CommonLibrary.PSAzureContext 2018-05-30T10:04:23.675 [Info] PowerShell function executed at:05/30/2018 10:04:23 2018-05-30T10:04:23.675 [Info] Function completed (Success, Id=386cd8a7-4e0b-4120-a669-353b28527ab3, Duration=1185ms)