.NET を使用して BLOB 用のユーザー委任 SAS から BLOB のプロパティを取得してみた

.NET アプリから BLOB のプロパティ、特に MD5 ハッシュを取得したく、実際にやってみました。

## 検証用コンソールアプリ作成

```bash:bash
prefix=mnrsas

dotnet new console --name $prefix --use-program-main

cd $prefix

dotnet run
```

## アプリに必要なパッケージを追加

```bash:bash
dotnet add package Azure.Identity
dotnet add package Azure.Storage.Blobs
```

## 検証用のコードに変更

```cs:Program.cs
using Azure;
using Azure.Identity;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;
using Azure.Storage.Sas;

namespace mnrsas;

class Program
{
    static void Main(string[] args)
    {
        // アカウント名
        string accountName = "mnrlabo";
        // アカウント名から BLOB エンドポイントを構築
        string endpoint = $"https://{accountName}.blob.core.windows.net";

        // DefaultAzureCredential を使用して BLOB サービスクライアントオブジェクトを作成
        BlobServiceClient blobServiceClient = new BlobServiceClient(
            new Uri(endpoint),
            new DefaultAzureCredential());

        // ユーザー委任 SAS を作成
        UserDelegationKey userDelegationKey = RequestUserDelegationKey(blobServiceClient);

        // ユーザー委任 SAS が追加された Uri オブジェクトを作成
        BlobClient blobClient = blobServiceClient
            .GetBlobContainerClient("wordpress")
            .GetBlobClient("20240308_a1b704f4d4941fad2473_20240811052117_archive.zip");
        Uri blobSASURI = CreateUserDelegationSASBlob(blobClient, userDelegationKey);

        // SAS 認証を使用して BLOB クライアントオブジェクトを作成
        BlobClient blobClientSAS = new BlobClient(blobSASURI);

        // BLOB プロパティを取得
        BlobProperties properties = blobClientSAS.GetProperties(new BlobRequestConditions(){}, CancellationToken.None);

        // BLOB プロパティの表示
        Console.WriteLine($"Blob Size: {properties.ContentLength} bytes");
        Console.WriteLine($"Content Type: {properties.ContentType}");
        Console.WriteLine($"Last Modified: {properties.LastModified}");

        // ContentHash を表示（バイト配列を 16 進数文字列に変換）
        if (properties.ContentHash != null)
        {
            string contentHashBase64 = Convert.ToBase64String(properties.ContentHash);
            Console.WriteLine($"Content Hash (Base64): {contentHashBase64}");
        }
    }

    static UserDelegationKey RequestUserDelegationKey(
        BlobServiceClient blobServiceClient)
    {
        // Get a user delegation key for the Blob service that's valid for 1 day
        UserDelegationKey userDelegationKey =
            blobServiceClient.GetUserDelegationKey(
                DateTimeOffset.UtcNow,
                DateTimeOffset.UtcNow.AddHours(1));

        return userDelegationKey;
    }

    static Uri CreateUserDelegationSASBlob(
        BlobClient blobClient,
        UserDelegationKey userDelegationKey)
    {
        // Create a SAS token for the blob resource that's also valid for 1 day
        BlobSasBuilder sasBuilder = new BlobSasBuilder()
        {
            BlobContainerName = blobClient.BlobContainerName,
            BlobName = blobClient.Name,
            Resource = "b",
            StartsOn = DateTimeOffset.UtcNow,
            ExpiresOn = DateTimeOffset.UtcNow.AddHours(1)
        };

        // Specify the necessary permissions
        sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write);

        // Add the SAS token to the blob URI
        BlobUriBuilder uriBuilder = new BlobUriBuilder(blobClient.Uri)
        {
            // Specify the user delegation key
            Sas = sasBuilder.ToSasQueryParameters(
                userDelegationKey,
                blobClient
                .GetParentBlobContainerClient()
                .GetParentBlobServiceClient().AccountName)
        };

        return uriBuilder.ToUri();
    }
}
```

## アプリを実行しプロパティを確認

```bash:bash
$ dotnet run
Blob Size: 106712197 bytes
Content Type: application/zip
Last Modified: 2024/08/11 5:22:40 +00:00
Content Hash (Base64): p1qsfJ2nS5St7XvX4uerfQ==
```

## Azure ポータル上のプロパティ表示

![dotnet-blob-properties-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/94c73af0-5a3f-224d-7543-9f6ca83bb0a2.png)

## 参考

https://learn.microsoft.com/ja-jp/azure/storage/blobs/storage-blob-user-delegation-sas-create-dotnet?tabs=packages-dotnetcli

https://learn.microsoft.com/ja-jp/dotnet/api/azure.storage.blobs.models.blobproperties?view=azure-dotnet