Search code examples
azurepowershellazure-devopsazure-powershellazure-pipelines-yaml

Connect-AzAccount with Azure Devops Pipeline?


I am finding difficulties in finding the best and secure way to use connect-azaccount with azure devops pipeline. I have in the pipeline the following this simple powershell script which is used to create azure resources. Just to simplify things I only used the creation of a resource group:

$Location = "Location Name"
$resourceGroupName = "Resource Group Name"

try {

    #Creation of Resource Group
    $resourceGroup = Get-AzResourceGroup -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue 

    if($null -eq $resourceGroup)
    {
        New-AzResourceGroup -Name $resourceGroupName -Location $Location
    }

    else
    {
        Write-Host "The ResourceGroup with the name: $resourceGroupName already exists."
    }

} 


catch 
{
    Write-Host "Error occurred: $_"
}

The problem here is when the pipeline is being run and it reaches the Powershell task, it gives me an error, Error occurred: Run Connect-AzAccount to login.

My issue here is that I honestly don't know which way is the most secure way to connect without typing any user credentials. It should directly connect and create the resources. Note that I am using Multi-Factor Authentication. In order to achieve that I found several solutions but I need help in choosing the best way. I found several solutions by adding a powershell task in the Yaml file. Here is the Yaml showing the powershell task to run the script:

  - task: PowerShell@2
    inputs:
      filePath: '$(Pipeline.Workspace)/Deploy/functionapp.ps1'

Option 1:

Connect-AzAccount -Tenant 'xxxx-xxxx-xxxx-xxxx' -SubscriptionId 'yyyy-yyyy-yyyy-yyyy'

Now the problem here is that the Tenant ID and Subscription are going to be visible in the code and that is a very bad practice

Option 2 is to use the following script:

$User = "[email protected]"
$PWord = ConvertTo-SecureString -String "<Password>" -AsPlainText -Force
$tenant = "<tenant id>"
$subscription = "<subscription id>"
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User,$PWord
Connect-AzAccount -Credential $Credential -Tenant $tenant -Subscription $subscription

This is very similar to the first, but if I am not mistaken it is limited to a specific user.

Option 3 is to use a service principal:

$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId  -ServicePrincipal

I don't know if creating a service principal will incur any costs and what steps should I do to make it work.

I am honestly new to all this, can someone please provide me what are the exact steps to achieve this. Thank you for your answers :)


Solution

  • The most secure way is to create an Azure Resource Manager service connection and use it in your pipeline. You can create it using automated way, or manually using previously created service principal.