Azure Storage Account へのアクセスはアクセスキーを使うと簡単なのですが、アクセスキーが漏洩すると大変です。そこで今回は、Azure 仮想マシンのマネージド ID 権限で Blob コンテナー一覧を表示する .NET 8 コンソールアプリで試してみました。
検証用の Azure Storage Account と コンテナーを 2 つ作成
bash
prefix=mnrblob
region=japaneast
az group create \
--name ${prefix}-rg \
--location $region
az storage account create \
--name ${prefix} \
--resource-group ${prefix}-rg \
--sku Standard_LRS
az storage container create \
--account-name ${prefix} \
--name test-container-01 \
--auth-mode login
az storage container create \
--account-name ${prefix} \
--name test-container-02 \
--auth-mode login
az storage container list \
--account-name ${prefix} \
--auth-mode login \
--output table
Name Lease Status Last Modified
----------------- -------------- -------------------------
test-container-01 2024-11-29T23:02:28+00:00
test-container-02 2024-11-29T23:02:47+00:00
ローカルで Blob コンテナー一覧を表示する .NET 8 コンソールアプリを作成
bash
dotnet new console -o $prefix --use-program-main
cd $prefix
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Identity
export AZURE_STORAGE_ACCOUNT_NAME=$prefix
code Program.cs
Program.cs
using System;
using System.Threading.Tasks;
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
class Program
{
static async Task Main(string[] args)
{
try
{
string accountName = Environment.GetEnvironmentVariable("AZURE_STORAGE_ACCOUNT_NAME") ?? "";
var blobServiceClient = new BlobServiceClient(
new Uri($"https://{accountName}.blob.core.windows.net"),
new DefaultAzureCredential());
await foreach (BlobContainerItem container in blobServiceClient.GetBlobContainersAsync())
{
Console.WriteLine($"Container name: {container.Name}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
}
ローカルで動作確認
bash
dotnet run
Container name: test-container-01
Container name: test-container-02
Azure CLI をログアウトして動作確認
bash
az logout
dotnet run
認証済み情報がなくなったので、以下のメッセージが表示されました。
Exception: DefaultAzureCredential failed to retrieve a token from the included credentials. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/defaultazurecredential/troubleshoot
- EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot
- WorkloadIdentityCredential authentication unavailable. The workload options are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/workloadidentitycredential/troubleshoot
- ManagedIdentityCredential authentication unavailable. No response received from the managed identity endpoint.
- Visual Studio Token provider can't be accessed at /Users/mnr/.IdentityService/AzureServiceAuth/tokenprovider.json
- Please run 'az login' to set up account
- PowerShell is not installed.
- Azure Developer CLI could not be found.
検証用の Azure 仮想マシンを作成
bash
az login
az vm create \
--resource-group ${prefix}-rg \
--name ${prefix}-vm \
--os-disk-name ${prefix}-vmOSDisk \
--image Canonical:ubuntu-24_04-lts:server:latest \
--size Standard_B1s \
--admin-username azureuser \
--generate-ssh-keys \
--assign-identity \
--nsg-rule NONE \
--public-ip-address-dns-name ${prefix}
az network nsg rule create \
--resource-group ${prefix}-rg \
--name Allow-SSH \
--nsg-name ${prefix}-vmNSG \
--priority 100 \
--source-address-prefixes $(curl -s inet-ip.info) \
--destination-port-ranges 22 \
--access Allow \
--protocol Tcp
別ターミナルで Azure 仮想マシンに SSH 接続
bash
prefix=mnrblob
region=japaneast
ssh azureuser@${prefix}.$region.cloudapp.azure.com
sudo apt-get update
sudo apt-get install -y dotnet-sdk-8.0
dotnet --version
prefix=mnrblob
dotnet new console -o $prefix --use-program-main
cd $prefix
dotnet add package Azure.Storage.Blobs
dotnet add package Azure.Identity
export AZURE_STORAGE_ACCOUNT_NAME=$prefix
cat <<EOF > Program.cs
using System;
using System.Threading.Tasks;
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
class Program
{
static async Task Main(string[] args)
{
try
{
string accountName = Environment.GetEnvironmentVariable("AZURE_STORAGE_ACCOUNT_NAME") ?? "";
var blobServiceClient = new BlobServiceClient(
new Uri($"https://{accountName}.blob.core.windows.net"),
new DefaultAzureCredential());
await foreach (BlobContainerItem container in blobServiceClient.GetBlobContainersAsync())
{
Console.WriteLine($"Container name: {container.Name}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Exception: {ex.Message}");
}
}
}
EOF
dotnet run
まだ、マネージド ID 権限を付与していないので、以下のエラーメッセージが表示されました。
Exception: This request is not authorized to perform this operation using this permission.
RequestId:899451a0-b01e-0016-56b6-423fc8000000
Time:2024-11-29T23:26:32.7651261Z
Status: 403 (This request is not authorized to perform this operation using this permission.)
ErrorCode: AuthorizationPermissionMismatch
Content:
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthorizationPermissionMismatch</Code><Message>This request is not authorized to perform this operation using this permission.
RequestId:899451a0-b01e-0016-56b6-423fc8000000
Time:2024-11-29T23:26:32.7651261Z</Message></Error>
Headers:
Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 899451a0-b01e-0016-56b6-423fc8000000
x-ms-client-request-id: 6695cfae-b890-4cbe-8d92-9fd46a08e176
x-ms-version: 2025-01-05
x-ms-error-code: AuthorizationPermissionMismatch
Date: Fri, 29 Nov 2024 23:26:31 GMT
Content-Length: 279
Content-Type: application/xml
元のターミナルで仮想マシンの マネージド ID に Storage Account Contributor 権限を付与
bash
az role assignment create \
--role "Storage Account Contributor" \
--assignee $(az vm show \
--resource-group ${prefix}-rg \
--name ${prefix}-vm \
--query identity.principalId \
--output tsv) \
--scope $(az storage account show \
--name ${prefix} \
--resource-group ${prefix}-rg \
--query id \
--output tsv)
もう一度、仮想マシンで動作確認
bash
dotnet run
Container name: test-container-01
Container name: test-container-02
後片付け
bash
az group delete \
--name ${prefix}-rg \
--yes
参考