これの続き。
uncaughtexception.hatenablog.com
1. リソース構成/必須Azureロールの訂正
前のエントリーでは、リソース構成とロール割り当てについて、
初期設定時は最低限、
・ 4種類のリソースが同じリソースグループ内にある
・ リソースグループと4種類のリソース、それぞれにReaderロールがある
というリソース構成/ロール割り当てが必須。
と書いた。
けどこれは👇のCloud Shellの設定用UIから設定する場合の話。

あくまで、この設定用UIがリソースを検索するために必要な構成/ロール。
REST APIで直接設定する場合は、リソース構成は自由だし、(設定だけなら)Readerロールすらいらなかった。
ただし実行時はストレージアカウントに対するReader and Data Accessロールが必要。
👆の設定用UIでリソースを選んだ後、どういうリクエストが飛ぶかを調べたら、
というエンドポイントに👇のようなJSONをHTTPでPUTしていて、JSONの中に必要なリソースのIDが書かれていた。
HTTP PUTしているJSON
{ "properties": { "preferredOsType": "linux", "preferredLocation": "southeastasia", "storageProfile": { "storageAccountResourceId": "/subscriptions/.../resourceGroups/.../providers/Microsoft.Storage/storageAccounts/...", "fileShareName": "...", "diskSizeInGB": 5 }, "terminalSettings": { "fontSize": "medium", "fontStyle": "monospace" }, "vnetSettings": { "networkProfileResourceId": "/subscriptions/.../resourceGroups/.../providers/Microsoft.Network/networkProfiles/...", "relayNamespaceResourceId": "/subscriptions/.../resourceGroups/.../providers/Microsoft.Relay/namespaces/...", "isolatedStorageProfile": { "storageAccountResourceId": "/subscriptions/.../resourceGroups/.../providers/Microsoft.Storage/storageAccounts/...", "fileShareName": "...", "diskSizeInGB": 5 }, "location": "japaneast" }, "userSubscription": "...", "sessionType": "Mounted", "networkType": "Isolated", "preferredShellType": "bash" } }
設定スクリプト
どこに何しているかがわかれば、あとはそれを実行するスクリプトを作るだけ。
az login SUBSCRIPTION_ID=$(az account show --query "id" --output tsv) # Azure RelayとNetwork Profileについては、ReaderロールもなくCLIで取ってくることができないので、リソースIDはべた書き AZURERELAY_ID=/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/.../providers/Microsoft.Relay/namespaces/... NETPROFILE_ID=/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/.../providers/Microsoft.Network/networkProfiles/... # ストレージアカウントは閲覧可能なので、CLIで取ってきてもリソースIDはべた書きでも、どっちでもよし。 # CLIで取ってくる場合のコマンドやフィルタ条件 (--query "[0].id") は適宜修正 STORAGEACCOUNT_ID=$(az storage account list --query "[0].id" --output tsv) STORAGEACCOUNT_SHARENAME=... # 実行 az rest \ --method put \ --url "https://management.azure.com/providers/Microsoft.Portal/userSettings/cloudconsole?api-version=2023-02-01-preview" \ --body " { \"properties\": { \"preferredOsType\": \"linux\", \"preferredLocation\": \"southeastasia\", \"storageProfile\": { \"storageAccountResourceId\": \"${STORAGEACCOUNT_ID}\", \"fileShareName\": \"${STORAGEACCOUNT_SHARENAME}\", \"diskSizeInGB\":5 }, \"terminalSettings\": { \"fontSize\": \"medium\", \"fontStyle\":\"monospace\" }, \"vnetSettings\": { \"networkProfileResourceId\": \"${NETPROFILE_ID}\", \"relayNamespaceResourceId\": \"${AZURERELAY_ID}\", \"isolatedStorageProfile\": { \"storageAccountResourceId\": \"${STORAGEACCOUNT_ID}\", \"fileShareName\": \"${STORAGEACCOUNT_SHARENAME}\", \"diskSizeInGB\": 5 }, \"location\": \"japaneast\" }, \"userSubscription\": \"${SUBSCRIPTION_ID}\", \"sessionType\": \"Mounted\", \"networkType\": \"Isolated\", \"preferredShellType\": \"bash\" } }"
使い方例
ふんわりとした使い方イメージ。
- 管理者が以下のリソースを準備する
- VNETやAzure Relayなど共通で必要なリソース
- Cloud Shell利用者ごとに、ストレージアカウントとファイル共有の準備とストレージアカウントのReader and Data Accessロールの付与をする
- 👆のスクリプトのリソースIDの箇所とファイル共有名等を修正して、利用者に「これを実行して」と配布する
- 利用者はローカル環境で受け取ったスクリプトを実行する
利用者が次にCloud Shellを開いた時は、設定が聞いてVNETに接続しているはず。
2. Azure Relayのネットワーク制限
デフォルトだと、Azure Relayのネットワークは、パブリックアクセスが全解放されている。

クライアントのIPアドレスが絞れるなら、IPアドレス制限をした方がいい。
ちなみに、ブラウザーとAzure Relayの間のやり取りでは、servicebus.windows.netドメインのホストにWebSocket接続をしている。
VNET接続の場合は専用のAzure Relayリソース、VNETなしの場合も共用のAzure Relayリソースが使われている。
なので、会社のネットワークなどのFirewall/Proxyあたりで、このドメイン全体をブロックされるとCloud Shellは動かないので注意。
コチラからは以上です。