セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.57 Azure REST APIでテンプレートをエクスポート|Azure&Entra IDスクリプト大作戦(4)
2024年11月05日配信
執筆者:山内 和朗
前回(vol.56)は、Invoke-RestMethodとcurlを用いて、サービスプリンシパルのアクセストークンを取得し、Azure REST APIからのリソース情報を取得することに成功しました。Azure仮想マシン(VM)の一覧を取得するという簡単なものでしたが、今回はもう少し複雑なことをしてみましょう。AzureポータルやAzure PowerShell、Azure CLIを使用せずに、指定したリソースグループのテンプレートを生成し、JSON形式で取得することに挑戦します。
Azure REST APIを使用したAzureのリソース情報の取得は、業務上必要になるため調査、勉強、検証しているところです。そんな中、社内のミーティングで「一括でリソース情報を取得する方法はないのか?」という話から、VMやストレージアカウントなどすべてのリソースにデプロイ情報をテンプレートとして生成し、ダウンロードする機能があることに気付きました(画面1)。また、すべてのリソースは、「リソースグループ」と呼ばれるコンテナーの1つに含まれるという事実にもです。リソースグループのレベルでテンプレートを生成し、ダウンロードできれば、そこにはリソースグループに含まれるすべてのリソースの情報が含まれているはずです。もし必要な情報がその中にすべてそろっていれば、Azure REST APIの膨大なサービスの中からAPIを探し、1つ1つ情報を取り出すという手間が省けそうです。Azure ポータルの各種管理ブレード(例えば「Virtual Machines」)に表示される設定内容は、「JSONビュー」で表示することができ、リソースのJSONをポータル画面の形式に変換して見やすくしているにすぎません。
画面1 Azureポータルを使用した、リソースのテンプレートの生成とダウンロード
Azureポータル、Azure PowerShell、Azure CLIには、リソースのデプロイ情報をテンプレートとしてダウンロードする機能があります。
Azure portal を使用してテンプレートをエクスポートする|Azure(Microsoft Learn)
Azure PowerShell を使用してテンプレートをエクスポートする|Azure(Microsoft Learn)
Azure CLI を使用してテンプレートをエクスポートする|Azure(Microsoft Learn)
そして、テンプレートのエクスポート機能はAzure REST APIにもいくつか用意されています。以下は、指定されたリソースグループをテンプレートとしてキャプチャして、JSON形式で取得することができるAPIです。
Resource Groups - Export Template|Azure REST API(Microsoft Learn)
APIの説明を見ても、何をどうすればよいのかさっぱり分かりません。しかし、試行錯誤の上、Azureポータルを使用して特定のリソースグループのテンプレートをダウンロードしたものと、同等のテンプレートを取得することに成功しました。
Azure REST APIにアクセスしてリソースグループのテンプレートを生成し、取得するには、PowerShellの標準のコマンドレットやcurlコマンドを使用できます。curlはあまり慣れていないので、使い慣れたPowerShellの方法で成功した手順を示します。
まず、前回と同じ方法でサービスプリンシパルのアクセストークンを取得します。
$clientid = "アプリケーション(クライアントID)" $clientsecret = "クライアントシークレットの値" $subscriptionid = "サブスクリプションID" $tenantid = "テナントID" $resource = "https://management.azure.com/" $tokenendpoint = "https://login.microsoftonline.com/$tenantid/oauth2/token" $body = @{ grant_type = "client_credentials" resource = $resource client_id = $clientid client_secret = $clientsecret } $tokenresponse = Invoke-RestMethod -Method Post -Uri $tokenendpoint -Body $body -ContentType "application/x-www-form-urlencoded" $accesstoken = $tokenresponse.access_token |
次に、前回Azure VMの一覧を取得したのと同様の方法を用いて、取得したアクセストークンを使用して以下のAPIにアクセスしてリソースグループの一覧を取得します(引き続き、同じPowerShellウィンドウで実行します)。
Resource Groups - List|Azure REST API(Microsoft Learn)
$headers = @{ 'Authorization' = "Bearer $accesstoken" 'Content-Type' = 'application/json' } $requesturi = "https://management.azure.com/subscriptions/$subscriptionid/resourcegroups?api-version=2021-04-01" $ret = (Invoke-RestMethod -Uri $requesturi -Headers $headers -Method Get).Value $ret |
(プレーンテキストで表示)
前回も触れましたが、Invoke-RestMethodは取得したJSON形式の値をPowerShellオブジェクトに自動変換します(画面2)。結果をJSON形式で取得したい場合は、$ret | ConvertTo-Jsonを実行してください。ConvertTo-Jsonは既定で第2レベルまでの子オブジェクトまで展開します。レベルは-Depthパラメーターで変更可能です。
画面2 Azure REST APIの1つにアクセスして、リソースグループの一覧を取得する
続いて、以下のAPIにアクセスして、テンプレートの生成を要求し、その後、応答に含まれる場所(location)にアクセスしてJSONテンプレートを取得します。
Resource Groups - Export Template|Azure REST API(Microsoft Learn)
取得したリソースグループの一覧から、1つ目のリソースグループを指定して、テンプレートを生成させてみましょう(引き続き、同じPowerShellウィンドウで実行します)。今回は、Invoke-RestMethodコマンドレットではなく、Invoke-WebRequestコマンドレットを使用します。その理由は、応答のステータスコード202(同意)を取得し、その応答のヘッダーに含まれる場所(location)の値を取得するためです(画面3)。Invoke-RestMethodコマンドレットで実行すると、何も応答が返ってこないので、実は、ここで数日間悩みました。
$resoucegname = $ret[0].Name $body = '{ "resources": [ "*" ], "options": "IncludeParameterDefaultValue,IncludeComments" }' $requesturi = "https://management.azure.com/subscriptions/$subscriptionid/resourcegroups/$resoucegname/exportTemplate?api-version=2021-04-01" $ret = (Invoke-WebRequest -Uri $requesturi -Headers $headers -Method Post -Body $body) $ret $requesturi = $ret.Headers.Location |
画面3 Azure REST APIにアクセスして、指定したリソースグループのテンプレートの生成を要求し、テンプレートの場所を取得する
テンプレートの場所(location)を取得できたら、そのURLにGETメソッドを送信し、結果をJSON形式でテキストファイルに保存します(画面4)。なお、Windows PowerShellでInvoke-RestMthodとConvertTo-Jsonを組み合わせた場合、' (アポストロフィ、シングルクォーテーション)を ¥u0027 とエスケープする既知の問題があるようです。そのためにテキストの置換(Replace)を含めています。PowerShell(pwsh)で実行する場合は、置換の必要はありません。
#$requesturi = $ret.Headers.Location # Windows PowerShell(powershell.exe) notepad $env:USERPROFILE¥export-template.json |
画面4 生成されたテンプレートの場所(location)にGETメソッドを送信し、JSON形式のテンプレートとして出力する
取得したJSON形式のテンプレートから目的の情報が得られるかどうかは、これから詳しく調べていく予定です。とりあえず、Azure REST APIから情報を取得する方法の選択肢が増えたことは間違いがありません。
・・・
追記:
Azureのテンプレートはリソースの構成を定義した器であり、同一構成のデプロイの繰り返しや反復的なプロセスに一貫性を提供するという、デプロイの自動化、インフラストラクチャのコード化のための手段であって、デプロイ済みのリソースそのものを示すものではありません。例えば、リソースの現在の状態や、VMにインストールされている拡張機能やアプリケーションの情報など、エクスポートしたテンプレートには含まれません。リソースの情報を一括で取得するという目的には不十分なようです。
ARM テンプレートに関してよく寄せられる質問|Azure(Microsoft Learn)