はじめに
前回の投稿のつづきです。
前回は、マネージド ID を使って Azure リソースを操作するために Connect-AZAccount
で Azure に接続する際の注意点について書きました。
今回は、マネージド ID を使って azcopy
によるストレージを操作する際の注意点について書きます。
検証環境
前回と同様、仮想マシン (Windows) 上で、同一マネージド ID を使って azcopy
でストレージを操作 (Blob の転送など) する PowerShell スクリプトを同じユーザーで同時に複数セッションで実行してみました。
実行する PowerShell スクリプトは、このように書いていました。
# マネージド ID のクライアント ID
$clientId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# Azure AD にログイン
azcopy login --identity --identity-client-id $clientId
# これ以降に自動化したい操作を実装
# コピー元 URI
$sourceUri = 'https://sourcexxxxx.blob.core.windows.net/source/'
# コピー先 URI
$destUri = 'https://destinationxxxxx.blob.core.windows.net/destination/'
# コンテナー配下をコピー
azcopy copy --recursive=true $sourceUri $destUri
ここでは、マネージド ID を使って Azure AD にログインするために azcopy login
で行っていますが、この点についてちょっとマズいことがあります。
気をつけること
問題点 : ログイン情報はキャッシュされる
azcopy login
で作成されたログイン情報は、ユーザープロファイル配下にキャッシュします。
一文だけなのでちょっと見落としそうですが、上記のドキュメントに以下のように記載されています。
このコマンドは、OS の組み込みメカニズムを使用して、現在のユーザーの暗号化されたログイン情報をキャッシュします。
検証したところ、このキャッシュされたログイン情報は、PowerShell セッション間で共有できてしまいます。前述したように、PowerShell スクリプトを同じユーザーで同時に複数実行すると、後続処理でエラーが発生するおそれがあります。
解決策
残念ながら azcopy login
で解決するのは困難です...自動化で使用するのは避けたほうがいいでしょう。だからといって、azcopy
が使えないというわけではありません。
前述の問題点を解決するには、前回紹介した Connect-AzAccount -Scope Process
で Azure に接続します。Blob の転送などを行う場合は、SAS トークン付きの URI を生成して行います。
冒頭の PowerShell スクリプトを以下のように修正します。
# マネージド ID のクライアント ID
$clientId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# Azure サブスクリプション ID
$subscriptionId = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# リソースグループ名
$resourceGroupName = 'rg-hoge'
# コピー元ストレージアカウント名
$sourceStorageAccountName = 'sourcexxxxx'
# コピー元コンテナー名
$sourceContainerName = 'source'
# コピー先ストレージアカウント名
$destStorageAccountName = 'destinationxxxxx'
# コピー先コンテナー名
$destContainerName = 'destination'
# Azureに接続
Connect-AzAccount -Scope Process -Identity -AccountId $clientId
# サブスクリプションを変更
Set-AzContext -Scope Process -Subscription $subscriptionId
# コピー元ストレージコンテキストの生成
$sourceStorageAccount = `
Get-AzStorageAccount -ResourceGroupName $resourceGroupName `
-Name $sourceStorageAccountName
$sourceStorageContext = $sourceStorageAccount.Context
# コピー先ストレージコンテキストの生成
$destStorageAccount = `
Get-AzStorageAccount -ResourceGroupName $resourceGroupName `
-Name $destStorageAccountName
$destStorageContext = $destStorageAccount.Context
# コピー元ストレージコンテナー URI を取得
$sourceStorageContainer = `
Get-AzStorageContainer -Name $sourceStorageContainerName `
-Context $sourceStorageContext
$sourceUri = $sourceStorageContainer.CloudBlobContainer.Uri.AbsoluteUri
# コピー先ストレージコンテナー URI を取得
$destStorageContainer = `
Get-AzStorageContainer -Name $destStorageContainerName `
-Context $destStorageContext
$destUri = $destStorageContainer.CloudBlobContainer.Uri.AbsoluteUri
# SAS トークンの有効期間の算出
$startTime = (Get-Date).AddSeconds(-300)
$expiryTime = $startTime.AddHours(1)
# コピー元 SAS トークンの生成
$sourceSASToken = `
New-AzStorageContainerSASToken -Name $sourceStorageContainerName `
-Context $sourceStorageContext `
-Permission 'racwld' `
-StartTime $startTime -ExpiryTime $expiryTime
# コピー先 SAS トークンの生成
$destSASToken = `
New-AzStorageContainerSASToken -Name $destStorageContainerName `
-Context $destStorageContext `
-Permission 'racwld' `
-StartTime $startTime -ExpiryTime $expiryTime
# Blob 転送
azcopy copy --recursive=true "$sourceUri$sourceSASToken" "$destUri$destSASToken"
まとめ
仮想マシンから、自動化で (マネージド ID を使って) azcopy
でストレージを操作する際 (PowerShell スクリプト) は、Azure に接続する場合は azcopy login
ではなく、Connect-AzAccount -Scope Process
で行いましょう。