Is there a type of service connection and corresponding task which facilitate Graph API calls?

Viewed 536

Current Azure Pipelines Task

As part of our CI/CD pipelines, we want to execute a couple of calls to GraphAPI, in a AAD B2C tenant to be exact. To enable this, we have created a service principal with the required permissions. As of right now, the pipeline uses a standard powershell task which in turn takes the secret to acquire a bearer token for Graph API. The objective is similar to this article: https://docs.microsoft.com/en-us/azure/active-directory-b2c/deploy-custom-policies-devops

We are about to expand this to other pipelines and I am hesitant to copy this authorization code to more places. In Azure DevOps I could use Variable Groups to help a bit, but then I still need to share some Powershell Code.

Is there something which could move the authentication to Azure DevOps? Similar to the Azure Powershell Task? I would still need some sort of scripting ability, since our GraphAPI calls are using data which is stored in the repository.

An option would be to wrap the existing Powershell task and expose something like a $bearerToken for the API calls, but I could not find any existing solution.

2 Answers

You can have a try convert the powershell task to a task group(Right click on the powershell task, and choose create task group). Then another pipelines in this project can add the task group. You will need to use inline script in the powershell task, so that you donot need to create a .ps1 file in other repo. If you want to output the $bearerToken to the follow tasks, you can use logging command echo "##vso[task.setvariable variable=Token]$bearerToken" in the script. Then you can refer the Token in follow tasks by $(Token)

But you still need to use Variable groups to store the secret and link it to the other pipeline.

Alternatively, you can use azure powershell cli in azure powershell task to get the bearer token for Graph API, since azure powershell task can hold the authentication using service connection. You can create a service connection using the service principal you created.

Then you can get the token for Graph API in the azure powershell task using the secrets configured in the service connection. See below script:

$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken

echo "##vso[task.setvariable variable=Token]$graphToken"
  

The equivalent commands for azure cli task is below:

$graphToken= & az account get-access-token --resource=https://graph.microsoft.com --query accessToken

echo "##vso[task.setvariable variable=Token]$graphToken"

So you can create a service connection. And use azure cli task or azure powershell task to run above inline scripts. And convert the task to task group. Then you can use this task group in other pipeline, and use the token in the other tasks by referring to $(Token)

By using the azure cli task or azure powershell task, you only need to configure the secret in the service connection. You will not need to expose any secret in the task or the scripts.

I discovered az rest which is even closer to my requirement than the answer by Levi Lu. It will acquire the required token automatically, without any extra code.

https://www.codeisahighway.com/native-azure-rest-api-calls-now-available-in-azure-cli-2-0-67/

az rest --method patch --url "https://graph.microsoft.com/v1.0/users/johndoe@azuresdkteam.onmicrosoft.com" --body "{\"displayName\": \"jondoe2\"}"

Though the commands mentioned by Levi Lu are also very helpful:

$context = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext
$graphToken = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate($context.Account, $context.Environment, $context.Tenant.Id.ToString(), $null, [Microsoft.Azure.Commands.Common.Authentication.ShowDialog]::Never, $null, "https://graph.microsoft.com").AccessToken
$graphToken= & az account get-access-token --resource=https://graph.microsoft.com --query accessToken
Related