はじめに
Azure 情報さまざまなリソースをコマンドラインで操作できる Azure CLI というツールがあります。
裏では Azure REST API を叩いていたりするようです。ときどき、Azure CLI による操作がどういう API を叩いてるのか(エンドポイント、ボディ)、どういうレスポンスが返ってきているのか気になることがあります。
プロキシ的なツールを挟んでパケットキャプチャする方法もありますが、もっと手軽に確認する方法ないかなと思って調べてみると、Azure CLI 側のデバッグ的な機能でできるようでした。
調べた限り --debug
オプションによる方法と、ログファイルの有効化の 2つの方法がありました。
それぞれ試してみた結果をまとめます。
- 環境
- azure-cli 2.43.0
方法1: --debug
オプションの利用
az hogehoge
コマンドに --debug
オプションを付けると、さまざまなデバッグ情報が表示されその中に、リクエストやレスポンスの情報がありました。
--debug
使用例
以下のコマンドは、既存のネットワークセキュリティグループ nsg01
に対して、description
を設定する例です。表面上はマージ的な操作です。例によって --debug
もつけます。
az network nsg rule update -g sakana --nsg-name nsg01 \ -n rule999 --description desc999 --debug
(参考: az network nsg rule
のリファレンス)
以下、実行して表示されたログを抜粋して、部分ごとに考察します。
(GET のリクエスト、レスポンス、PUT のリクエスト、レスポンス)
GET のリクエスト
以下のように、ネットワークセキュリティグループ nsg01
のルール rule999
の情報を GET する様子を確認しました。
cli.azure.cli.core.sdk.policies: Request URL: 'https://management.azure.com/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999?api-version=2022-01-01' cli.azure.cli.core.sdk.policies: Request method: 'GET' cli.azure.cli.core.sdk.policies: Request headers: cli.azure.cli.core.sdk.policies: 'Accept': 'application/json' cli.azure.cli.core.sdk.policies: 'x-ms-client-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'CommandName': 'network nsg rule update' cli.azure.cli.core.sdk.policies: 'ParameterSetName': '-g --nsg-name -n --description --debug' cli.azure.cli.core.sdk.policies: 'User-Agent': 'AZURECLI/2.43.0 (PIP) (AAZ) azsdk-python-core/1.26.2 Python/3.9.16 (macOS-12.6-x86_64-i386-64bit)' cli.azure.cli.core.sdk.policies: 'Authorization': '*****' cli.azure.cli.core.sdk.policies: Request body: cli.azure.cli.core.sdk.policies: This request has no body urllib3.connectionpool: Starting new HTTPS connection (1): management.azure.com:443
なぜ 事前に GET するかの考察
対応する API リファレンスは Security Rules - Get
。
セキュリティルールに関するリファレンスを確認すると、特定の設定項目のみをマージ、つまり PATCH する方法はありませんでした。できるのは PUTです。
PUT するには設定差分の情報だけでなく、該当ルールの情報一式(direction
や priority
など)が必要です。そうしないと、API 使用上必須のパラメーターが不足して設定できなかったり(400 Bad Request
)、設定がデフォルトに戻ったりしてしまいます。
一方で、az network nsg rule update
コマンドとしては、キーとなる情報(-g
、--nsg-name
、 -n
)以外は、設定差分(今回は --description
)しか指定していません。そのため、他の必要な情報一式を取得するために事前に GET しているのかなと思いました。
ヘッダーについての補足
リクエストヘッダーについては、あくまで Azure CLI 側が付加するものだけが表示されてるようでした。プロキシツールを併用してパケットキャプチャしたところ、他にもたとええば以下のような基本的なヘッダーも付加されてることを確認しました。
Host: management.azure.com Connection: keep-alive
なお、'Authorization': '*****'
は、ブログ用にマスクしたのではなく、もともとマスクされて表示されました。
GET に対するレスポンス
先ほどの GET するリクエストに続いて、以下のレスポンスのログが表示されました。Response content
のところで、レスポンスのボディがあります。
urllib3.connectionpool: https://management.azure.com:443 "GET /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999?api-version=2022-01-01 HTTP/1.1" 200 None cli.azure.cli.core.sdk.policies: Response status: 200 cli.azure.cli.core.sdk.policies: Response headers: cli.azure.cli.core.sdk.policies: 'Cache-Control': 'no-cache' cli.azure.cli.core.sdk.policies: 'Pragma': 'no-cache' cli.azure.cli.core.sdk.policies: 'Transfer-Encoding': 'chunked' cli.azure.cli.core.sdk.policies: 'Content-Type': 'application/json; charset=utf-8' cli.azure.cli.core.sdk.policies: 'Content-Encoding': 'gzip' cli.azure.cli.core.sdk.policies: 'Expires': '-1' cli.azure.cli.core.sdk.policies: 'ETag': 'W/"XXXXXXXX-xxxx-xxxx-xxxx-xxxxxxxxxxxx"' cli.azure.cli.core.sdk.policies: 'Vary': 'Accept-Encoding' cli.azure.cli.core.sdk.policies: 'x-ms-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'x-ms-correlation-request-id': 'xxxxxxxx-XXXX-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'x-ms-arm-service-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains' cli.azure.cli.core.sdk.policies: 'Server': 'Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0' cli.azure.cli.core.sdk.policies: 'x-ms-ratelimit-remaining-subscription-reads': '11999' cli.azure.cli.core.sdk.policies: 'x-ms-routing-request-id': 'JAPANEAST:20230108T132147Z:xxxxxxxx-XXXX-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'X-Content-Type-Options': 'nosniff' cli.azure.cli.core.sdk.policies: 'Date': 'Sun, 08 Jan 2023 13:21:46 GMT' cli.azure.cli.core.sdk.policies: Response content: cli.azure.cli.core.sdk.policies: { "name": "rule999", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999", "etag": "W/\"XXXXXXXX-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", "type": "Microsoft.Network/networkSecurityGroups/securityRules", "properties": { "provisioningState": "Succeeded", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "443", "sourceAddressPrefix": "203.0.113.0/24", "destinationAddressPrefix": "*", "access": "Allow", "priority": 999, "direction": "Inbound", "sourcePortRanges": [], "destinationPortRanges": [], "sourceAddressPrefixes": [], "destinationAddressPrefixes": [] } }
update
前の設定情報なので、まだ description
はありません。
PUT のリクエスト
いよいよ、実際の設定変更のための PUT です。
cli.azure.cli.core.sdk.policies: Request URL: 'https://management.azure.com/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999?api-version=2022-01-01' cli.azure.cli.core.sdk.policies: Request method: 'PUT' cli.azure.cli.core.sdk.policies: Request headers: cli.azure.cli.core.sdk.policies: 'Content-Type': 'application/json' cli.azure.cli.core.sdk.policies: 'Accept': 'application/json' cli.azure.cli.core.sdk.policies: 'Content-Length': '496' cli.azure.cli.core.sdk.policies: 'x-ms-client-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'CommandName': 'network nsg rule update' cli.azure.cli.core.sdk.policies: 'ParameterSetName': '-g --nsg-name -n --description --debug' cli.azure.cli.core.sdk.policies: 'User-Agent': 'AZURECLI/2.43.0 (PIP) (AAZ) azsdk-python-core/1.26.2 Python/3.9.16 (macOS-12.6-x86_64-i386-64bit)' cli.azure.cli.core.sdk.policies: 'Authorization': '*****' cli.azure.cli.core.sdk.policies: Request body: cli.azure.cli.core.sdk.policies: {"id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999", "name": "rule999", "properties": {"access": "Allow", "description": "desc999", "destinationAddressPrefix": "*", "destinationPortRange": "443", "direction": "Inbound", "priority": 999, "protocol": "Tcp", "sourceAddressPrefix": "203.0.113.0/24", "sourcePortRange": "*"}, "type": "Microsoft.Network/networkSecurityGroups/securityRules"}
対応する API リファレンスは Security Rules - Create Or Update
。
Request body
のところで設定値が確認できます。わかりやすいようにここだけ整形して再掲します。
{ "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999", "name": "rule999", "properties": { "access": "Allow", "description": "desc999", "destinationAddressPrefix": "*", "destinationPortRange": "443", "direction": "Inbound", "priority": 999, "protocol": "Tcp", "sourceAddressPrefix": "203.0.113.0/24", "sourcePortRange": "*" }, "type": "Microsoft.Network/networkSecurityGroups/securityRules" }
事前に GET した情報に対して、az network nsg rule update
コマンドの --description
で指定した description
をマージしたような内容になっています。
PUT に対するレスポンス
続いて、先ほどの PUT のに対するレスポンスが表示されました。
urllib3.connectionpool: https://management.azure.com:443 "PUT /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999?api-version=2022-01-01 HTTP/1.1" 200 None cli.azure.cli.core.sdk.policies: Response status: 200 cli.azure.cli.core.sdk.policies: Response headers: cli.azure.cli.core.sdk.policies: 'Cache-Control': 'no-cache' cli.azure.cli.core.sdk.policies: 'Pragma': 'no-cache' cli.azure.cli.core.sdk.policies: 'Transfer-Encoding': 'chunked' cli.azure.cli.core.sdk.policies: 'Content-Type': 'application/json; charset=utf-8' cli.azure.cli.core.sdk.policies: 'Content-Encoding': 'gzip' cli.azure.cli.core.sdk.policies: 'Expires': '-1' cli.azure.cli.core.sdk.policies: 'Retry-After': '10' cli.azure.cli.core.sdk.policies: 'Vary': 'Accept-Encoding' cli.azure.cli.core.sdk.policies: 'x-ms-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'Azure-AsyncOperation': 'https://management.azure.com/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/Microsoft.Network/locations/japaneast/operations/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx?api-version=2022-01-01' cli.azure.cli.core.sdk.policies: 'x-ms-correlation-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'Azure-AsyncNotification': 'Enabled' cli.azure.cli.core.sdk.policies: 'x-ms-arm-service-request-id': 'xxxxxxxx-xxxx-xxxx-XXXX-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains' cli.azure.cli.core.sdk.policies: 'Server': 'Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0' cli.azure.cli.core.sdk.policies: 'x-ms-ratelimit-remaining-subscription-writes': '1199' cli.azure.cli.core.sdk.policies: 'x-ms-routing-request-id': 'JAPANEAST:20230108T132147Z:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' cli.azure.cli.core.sdk.policies: 'X-Content-Type-Options': 'nosniff' cli.azure.cli.core.sdk.policies: 'Date': 'Sun, 08 Jan 2023 13:21:46 GMT' cli.azure.cli.core.sdk.policies: Response content: cli.azure.cli.core.sdk.policies: { "name": "rule999", "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999", "etag": "W/\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", "type": "Microsoft.Network/networkSecurityGroups/securityRules", "properties": { "provisioningState": "Updating", "description": "desc999", "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "443", "sourceAddressPrefix": "203.0.113.0/24", "destinationAddressPrefix": "*", "access": "Allow", "priority": 999, "direction": "Inbound", "sourcePortRanges": [], "destinationPortRanges": [], "sourceAddressPrefixes": [], "destinationAddressPrefixes": [] } }
レスポンスコードは 200
でした。リファレンスによると 200
が更新、201
が作成とのことです。今回は既存のルールに description
を設定するという更新なので 200
なのでしょう。
レスポンスボディには、更新後の結果が返ってきました。description
も設定されています。
その他のリクエスト(処理の完了待ち)
ここまでのログでは省略しましたが、設定が完了したかどうか調べるようなリクエストもされていました。
--no-wait
オプションをつけると、このリクエストをしなくなりました。
ここまでで、--debug
オプションによるリクエストの内容を確認できました。
方法2: ログファイルの有効化
次は、az
コマンドのオプションではなく、設定ファイルでログファイルを有効にして、そのファイルを確認する方法です。
ひと手間かかりますが、通常の出力とデバッグ出力を分けられる点では便利です。
設定の準備
デフォルトでは、az
コマンドのログ情報はファイルに出力されません。出力させるには構成ファイル(デフォルト ~/.azure/config
)での仕込みが必要です。
~/.azure/config
:
[logging] enable_log_file = true
上記の設定で、ファイル出力が有効になります。出力先ファイルはデフォルトでは ~/.azure/logs/
ディレクトリの az.log
でした。ディレクトリは [logging]
セクションの log_dir
という設定項目で変更できます。
構成ファイル内の全項目はドキュメントを参照してください。
ログファイル有効化状態での実行例
前述のログファイル出力を有効化した状態で、az
コマンドを実行します。
内容は --debug
オプション利用時と同じく、既存のネットワークセキュリティグループ nsg01
に対して、description
を設定する例です。
違いは --debug
オプションを指定しないことです。
az network nsg rule update -g sakana --nsg-name nsg01 \ -n rule999 --description desc999
実行結果の確認
コマンドの実行結果自体は通常と同じです。
~/.azure/logs/az.log
を確認するとログが書き込まれていました。リクエストやレスポンスの内容の表示は --debug
オプション利用時とおなじような感じなので、説明は省略します。時刻も載ってるところが特徴かなと思います。
...(略)... 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : Request URL: 'https://management.azure.com/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/sakana/providers/Microsoft.Network/networkSecurityGroups/nsg01/securityRules/rule999?api-version=2022-01-01' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : Request method: 'GET' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : Request headers: 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : 'Accept': 'application/json' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : 'x-ms-client-request-id': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : 'CommandName': 'network nsg rule update' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : 'ParameterSetName': '-g --nsg-name -n --description' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : 'User-Agent': 'AZURECLI/2.43.0 (PIP) (AAZ) azsdk-python-core/1.26.2 Python/3.9.16 (macOS-12.6-x86_64-i386-64bit)' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : 'Authorization': '*****' 2419 : 2023-01-09 20:09:04,748 : DEBUG : cli.azure.cli.core.sdk.policies : Request body: 2419 : 2023-01-09 20:09:04,749 : DEBUG : cli.azure.cli.core.sdk.policies : This request has no body ...(略)...
おわりに
Azure CLI が裏で叩いてる REST API のリクエストとレスポンスを確認する方法として、
--debug
オプションの利用- ログファイルの有効化
を試してみました。
Azure CLI を使っていて、これどうやってだろう?というときになったときに使っていきたいと思います。