Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VSTS Build and PowerShell and AzureAD Authentication

I have a VSTS project connected via a Service Principal to an Azure subscription through an Azure Resource Manager endpoint. This works fine for my builds that configure ARM resources via templated, parameter driven deployments.

I have an additional requirement to set up Azure AD groups as part of the build. I have a script that works fine from my local machine. When I deployed it via the build and it executed on the hosted build controller, the script could initially not find the AzureAD module. I got around this by including the script in git Repo and accessing it through:

$adModulePath = $PSScriptRoot + "\PsModules\AzureAD\2.0.0.131\AzureAD.psd1"
Import-Module $adModulePath 

However, I now have another problem when it comes to running New-AzureADGroup. The script requires Connect-AzureAD to be run before the command is issued. This works fine by hardcoding a credential but I don't want to do this, I want it to run under the context of the SPN created, which is running the scripts on the hosted build controller.

So, the question is, can I get the current context of the Azure PowerShell execution SPN and pass that to Connect-AzureAD to avoid storing credential in plain text? Am I missing a trick? Are there any alternatives?

My current code is as below, the commented connection works fine from the command like with hard coded values. The call with no parameters presents the login UI which terminates the build since it is obviously not interactive.

## Login to Azure
#$SecurePassword = ConvertTo-SecureString $AdminPassword -AsPlainText -Force
#$AdminCredential = New-Object System.Management.Automation.PSCredential ($AdminUserEmailAddress, $SecurePassword)
#Connect-AzureAD -Credential $AdminCredential

Connect-AzureAD

Write-Output "------------------ Start: Group Creation ------------------"

$TestForAdminGroup = Get-AzureADGroup -SearchString $AdminGroup
$TestForContributorGroup = Get-AzureADGroup -SearchString $ContributorGroup
$TestForReaderGroup = Get-AzureADGroup -SearchString $ReaderGroup

Thanks

like image 554
Murray Foxcroft Avatar asked Oct 03 '17 22:10

Murray Foxcroft


2 Answers

This is possible. Got it working today for my own VSTS extension that I released a while ago. My extension is using a Azure Resource Manager endpoint as input.

Running it now on a Microsoft Hosted Visual Studio 2017 agent pool using the below code. See for more information my post on how to use AzureAD PowerShell cmdlets on VSTS agent.

Write-Verbose "Import AzureAD module because is not on default VSTS agent"
$azureAdModulePath = $PSScriptRoot + "\AzureAD\2.0.1.16\AzureAD.psd1"
Import-Module $azureAdModulePath 

# Workaround to use AzureAD in this task. Get an access token and call Connect-AzureAD
$serviceNameInput = Get-VstsInput -Name ConnectedServiceNameSelector -Require
$serviceName = Get-VstsInput -Name $serviceNameInput -Require
$endPointRM = Get-VstsEndpoint -Name $serviceName -Require

$clientId = $endPointRM.Auth.Parameters.ServicePrincipalId
$clientSecret = $endPointRM.Auth.Parameters.ServicePrincipalKey
$tenantId = $endPointRM.Auth.Parameters.TenantId

$adTokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/token"
$resource = "https://graph.windows.net/"

$body = @{
    grant_type    = "client_credentials"
    client_id     = $clientId
    client_secret = $clientSecret
    resource      = $resource
}

$response = Invoke-RestMethod -Method 'Post' -Uri $adTokenUrl -ContentType "application/x-www-form-urlencoded" -Body $body
$token = $response.access_token

Write-Verbose "Login to AzureAD with same application as endpoint"
Connect-AzureAD -AadAccessToken $token -AccountId $clientId -TenantId $tenantId
like image 124
LockTar Avatar answered Oct 25 '22 00:10

LockTar


To conclude, the Powershell module can’t share the same context and you need to store the credential in secret variable in VSTS.

like image 2
starian chen-MSFT Avatar answered Oct 25 '22 00:10

starian chen-MSFT