2

I am trying to create a VSTS task, which should create an AD application. Taken the DeployAzureResouceGroup as a sample, I have created to following script:

[CmdletBinding()]
param()

Trace-VstsEnteringInvocation $MyInvocation
Import-VstsLocStrings "$PSScriptRoot\Task.json"
$connectedServiceNameSelector = Get-VstsInput -Name "connectedServiceNameSelector" -Require
$connectedServiceName = Get-VstsInput -Name "connectedServiceName"
$connectedServiceNameClassic = Get-VstsInput -Name "connectedServiceNameClassic"
$domains = (Get-VstsInput -Name "domains").Split(";")
$appName = Get-VstsInput -Name "appName"

if($connectedServiceNameSelector -eq "ConnectedServiceNameClassic")
{
    $connectedServiceName = $connectedServiceNameClassic
    $action = $actionClassic
    $resourceGroupName = $cloudService
}

Import-Module $PSScriptRoot\ps_modules\VstsAzureHelpers_
Initialize-Azure

# Import the loc strings.
Import-VstsLocStrings -LiteralPath $PSScriptRoot/Task.json

# Import all the dlls and modules which have cmdlets we need
Import-Module "$PSScriptRoot\DeploymentUtilities\Microsoft.TeamFoundation.DistributedTask.Task.Deployment.Internal.psm1"
Import-Module "$PSScriptRoot\DeploymentUtilities\Microsoft.TeamFoundation.DistributedTask.Task.Deployment.dll"

# Load all dependent files for execution
. "$PSScriptRoot\Utility.ps1"


try
{
    Validate-AzurePowerShellVersion
    $azureUtility = Get-AzureUtility "$connectedServiceName"
    Write-Verbose "Loading $azureUtility"
    . "$PSScriptRoot\$azureUtility"
    Write-Output "test"
    Write-Output "Creating a new Application in AAD (App URI -)" -Verbose
    $azureAdApplication = New-AzureRmADApplication -DisplayName "test" -IdentifierUris "https://app.com" -HomePage "https://app.com"
    $appId = $azureAdApplication.ApplicationId
    Write-Output "Azure AAD Application creation completed successfully (Application Id: $appId)" -Verbose

    Write-Verbose "Completing Azure Resource Group Deployment Task" -Verbose
}
catch
{
    Write-TaskSpecificTelemetry "UNKNOWNDEP_Error"
    throw
}

When I use a Service principal as Service Endpoint user, I got the error Resource me not found.

When I use my custom AD account, I got the error:Run Login-AzureRmAccount to login.

What am I doing wrong? How can I get this script working?

Identity
  • 1,553
  • 1
  • 22
  • 44
  • Based on these link (http://answers.flyppdevportal.com/MVC/Post/Thread/0582b2bd-d7f7-49c3-9e9b-f8b0b040ba77?category=windowsazuread and http://stackoverflow.com/questions/34762918/adding-applications-programmatically-in-azure-ad-using-client-credentials-flow), it is impossible to create another service principal from a service principal, so it is impossible to achieve that with your way. You can call New-AzureRmADApplication command in Azure PowerShell step to verify it (throws same error). – starian chen-MSFT Jan 24 '17 at 05:25
  • You can try to authenticate with username and password (https://www.returngis.net/en/2015/06/add-azureaccount-without-prompt-authenticating-and-automating-scripts-in-powershell/), then call that command. – starian chen-MSFT Jan 24 '17 at 05:26
  • When you use Azure AD account, change "New-AzureRmADApplication" to "New-AzureADApplication" and then try again. – Eddie Chen - MSFT Jan 24 '17 at 08:25

1 Answers1

1

If you don't need Powershell scripting, go install Azure AD Application Management extension from https://marketplace.visualstudio.com/items?itemName=RalphJansen.Azure-AD-Application-Management You can add new tasks from pipeline GUI for managing AD applications.

If you do need Powershell scripting, then things get tricky. Get Powershell code from https://stackoverflow.com/a/51848069/1548275 as a base. The difference is, that if you're not running your code from an extension, you don't have Get-VstsInput nor Get-VstsEndpoint available to execute.

Also, you don't have AzureAD module cmdlets to run. You need to get the Nuget-package, unzip it to your own repo and have it as part of your scripts to be later Import-Module in a pipeline task.

Finally, you need an auth token for Graph API. As the extension code shows, you will need 3 variables:

  • $tenantId = (Get-AzureRmSubscription).TenantId
  • $clientId = (Get-AzureRmADServicePrincipal -DisplayName "Your Project Service Connection name from Azure AD App Registrations").ApplicationId.Guid
  • $clientSecret = 'hard-coded, reset SPN password'

As you can see, an extension would have access to all three, but regular script (to my knowledge) doesn't.

SPN password reset is covered in The Net. Briefly, it is something like this:

$clientId = (Get-AzureRmADServicePrincipal -DisplayName "Your Project Service Connection name from Azure AD App Registrations").Id.Guid
$password = ConvertTo-SecureString –asplaintext –force "oh, this is very secret!"
New-AzureRmADSpCredential -ObjectId $clientId -Password $password

Also: Update the plaintext password into Azure DevOps project settings, Service Connections for Pipeline to know about the update.

Jari Turkia
  • 1,184
  • 1
  • 21
  • 37
  • Nice script. You indeed need those 3 properties. If you create a new secret, specify the enddate because otherwise it will be valid for (I thought) a year by default. Also, don't forget to remove expired credentials for clarity. – LockTar Feb 04 '19 at 09:15
  • Given the complexity of this topic, I wrote an in-detail blog post how I'm doing my AD app setup from Azure DevOps pipeline task, read the post here https://blog.hqcodeshop.fi/archives/435-Setting-up-Azure-AD-Application-from-Azure-DevOps-pipeline-Powershell-task,-Part-2-of-2-The-scripts.html – Jari Turkia May 06 '19 at 13:08