So far I used the Azure PowerShell task to execute PowerShell scripts in an Azure Context (https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-powershell?view=vsts). Due to generalization efforts I want now to create a custom task (see e.g. http://www.donovanbrown.com/post/how-do-i-upload-a-custom-task-for-build) that runs a PowerShell script in an Azure Context, i.e. that authenticates against a connection endpoint in Azure DevOps.
How can I achieve this?
First of all you need a service principal (see e.g. https://docs.microsoft.com/en-us/powershell/azure/create-azure-service-principal-azureps?view=azps-1.1.0) and a service connection (see e.g. https://docs.microsoft.com/en-us/azure/devops/pipelines/library/connect-to-azure?view=vsts).
In the custom task in task.json
add an input to be able to select the service connection:
"inputs": [
{
"name": "ConnectedServiceName",
"type": "connectedService:AzureRM",
"label": "Azure RM Subscription",
"defaultValue": "",
"required": true,
"helpMarkDown": "Select the Azure Resource Manager subscription for the deployment."
}
]
In the task (the powershell script) you get this input via
$serviceNameInput = Get-VstsInput -Name ConnectedServiceNameSelector -Default 'ConnectedServiceName'
$serviceName = Get-VstsInput -Name $serviceNameInput -Default (Get-VstsInput -Name DeploymentEnvironmentName)
Then authenticate:
try {
$endpoint = Get-VstsEndpoint -Name $serviceName -Require
if (!$endpoint) {
throw "Endpoint not found..."
}
$subscriptionId = $endpoint.Data.SubscriptionId
$tenantId = $endpoint.Auth.Parameters.TenantId
$servicePrincipalId = $endpoint.Auth.Parameters.servicePrincipalId
$servicePrincipalKey = $endpoint.Auth.Parameters.servicePrincipalKey
$spnKey = ConvertTo-SecureString $servicePrincipalKey -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential($servicePrincipalId,$spnKey)
Add-AzureRmAccount -ServicePrincipal -TenantId $tenantId -Credential $credentials
Select-AzureRmSubscription -SubscriptionId $subscriptionId -Tenant $tenantId
$ctx = Get-AzureRmContext
Write-Host "Connected to subscription '$($ctx.Subscription)' and tenant '$($ctx.Tenant)'..."
} catch {
Write-Host "Authentication failed: $($_.Exception.Message)..."
}
Edit:
It is useful to clear the context at the beginning respectively the end of the script. You can do that via
Clear-AzureRmContext -Scope Process
Disable-AzureRmContextAutosave
at the beginning and
Disconnect-AzureRmAccount -Scope Process
Clear-AzureRmContext -Scope Process
at the end.