kkamegawa's weblog

Visual Studio,TFS,ALM,VSTS,DevOps関係のことについていろいろと書いていきます。Google Analyticsで解析を行っています

Azure PipelinesのYAMLでPATを参照する

何回も書いているにもかかわらず、そのたびに過去のパイプラインを見直すので自分用まとめ。

Azure PipelinesではLibraryに登録した値をパイプライン中で参照することができます。

learn.microsoft.com

デプロイ先とかリージョン名とかであれば平文でもいいですが、パスワードやトークンであれば🔒を設定しておくことで初回登録以降表示されなくなります。Azure Pipelinesの中でも暗号化されているので、二度と平文の表示はできません(そのはずです)。より厳密に保護したい場合、Azure KeyVaultに登録してください。シームレスに連携しているので、参照している先がどちらかというだけです。

learn.microsoft.com

KeyVaultに入れておくとLog Analyticsでアクセスの検索もできますし、そもそもKeyVaultのシークレットを管理する人とパイプラインを管理する人の分離ができます。そういうセキュリティ上の要件がある時は使ってください。一人で使うだけなら別に要らないとは思います。

パイプラインからLibraryを使う場合、Permissionから使用できるパイプラインの指定を忘れないようにしてください。ほっとくと数日間動いてないってことがあります(警告出るのですぐわかります)。

で、本題のこのPAT(個人用アクセストークン)をYAML内で参照する方法です。

YAML内で使用を宣言

variables:
- group: ReleasenoteGen

- task: PowerShell@2
  displayName: 'Check Release Notes for Azure DevOps'
  inputs:
    filePath: '$(Build.SourcesDirectory)/vsts-translate/create-task-issue.ps1'
    pwsh: true
  env:
    PAT: $(PAT)

variablesセクションのgroupにLibraryの値を指定します。これでLibraryに登録しているPATという変数の値が参照できます。これをPowerShell / Bashなどで使う場合、envに環境変数値のペアで登録しておくとスクリプト内で参照できます。例えばPowerShellの例。

$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$ENV:PAT"))
$header = @{authorization = "Basic $token"}
$uri = 'https://dev.azure.com/{organization}/{Project}/{Team}/_apis/wit/wiql/{QueryID}?api-version=7.1-preview.2'
$json = Invoke-RestMethod -Uri $Uri -Method Get -ContentType "application/json" -Headers $header
if($json.workItems.Count -gt 0) {
  write-host "work in progress"
  exit 
}

PowerShellでは$ENV:{環境変数名}でOSの環境変数の参照ができます。$ENV:PATでYAMLで設定した環境変数をスクリプト内で使うことが可能になります。余談ですがこのREST APIは事前に登録したQuery(WIQL)を呼び出すものです。クエリで条件に引っかかるものがあればスクリプトを終了しています。

Azure DevOps CLIから参照する

learn.microsoft.com

Azure DevOpsを制御するためのCLIがAzure CLIの拡張機能として提供されています。REST API使うよりも便利なケースがありますので、こちらを使うことがあります。最近ではREST APIでどうしてもタスク作成時に日本語渡せなかったので、挫折してaz boards work-item create使いました。このCLIも中身はPythonで同じREST API呼び出しているはずなのでソース見ればいいのですが…。

Azure DevOps CLIは基本的にインタラクティブな処理を前提にしていますが、自動化用にいくつかの方法があります。

  1. 標準入力のリダイレクト echo $PAT | az devops login --org {organization URL}
  2. AZURE_DEVOPS_EXT_PAT環境変数を使う

1に関してはストレージに格納されちゃうからちゃんとaz devops logoutしろよ、という警告が出ます。スクリプトで使うならちゃんとログアウトしましょう。

WARNING: Failed to store PAT using keyring; falling back to file storage.
WARNING: You can clear the stored credential by running az devops logout.
WARNING: Refer https://aka.ms/azure-devops-cli-auth to know more on sign in with PAT.

learn.microsoft.com

ファイルからリダイレクトする方法もありますが、PATをファイル(レポジトリ)に置いておくのはちょっと…ということで、2番目の方法を使います。これはAzure DevOps CLIのログイン処理なしでaz boardsコマンド実行するときに自動的に参照してくれるので便利です。

- task: Bash@3
    displayName: 'Create work item'
    inputs:
      targetType: 'inline'
      script: 'az boards work-item create --title "リリースノートの翻訳を行う" --type "User Story" --area "エリア名" --org https://dev.azure.com/{org名}/ -p {project} --assigned-to ID'
    env:
      AZURE_DEVOPS_EXT_PAT: $(PAT)

envに指定しておくと、上のvariablesで定義されているPATAZURE_DEVOPS_EXT_PATにマップしてくれるので、az devops loginしなくても自動的にログイン(というかREST APIのトークンとして参照)してくれます。こっちのほうがいいんじゃないかな。

YAML内での参照方法の注意点

Azure Pipelinesには複数の変数があります。

マクロ(タスク実行前)、テンプレート(YAMLをパースするとき)、ランタイム(実行時)と置換されるタイミングが違うので、気をつけてください。最初に使うのはマクロでしょう。⁠.NETであれば-c $(BuildConfiguration)とかそういった類ですね。