コンテナー、ディレクトリ、または BLOB のユーザー委任 SAS を .NET で作成する

Shared Access Signature (SAS) を使用すると、ストレージ アカウント内のコンテナーと BLOB への制限付きアクセスを許可できます。 SAS を作成するときに、クライアントがアクセスできる Azure Storage リソース、それらのリソースに対するアクセス許可、SAS の有効期間などの制約を指定します。

すべての SAS はキーによって署名されます。 次の 2 つの方法のいずれかで SAS に署名できます。

  • Azure Active Directory (Azure AD) の資格情報を使用して作成されたキーを使用する。 Azure AD の資格情報を使用して署名された SAS は、"ユーザー委任" SAS です。 ユーザー委任 SAS を作成するクライアントには、Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey アクションを含む Azure RBAC ロールを割り当てる必要があります。 詳細については、「ユーザー委任 SAS を作成する」を参照してください。
  • ストレージ アカウント キーを使用する。 サービス SASアカウント SAS は、どちらもストレージ アカウント キーを使用して署名されます。 サービス SAS を作成するクライアントには、アカウント キーへの直接アクセス権を付与するか、Microsoft.Storage/storageAccounts/listkeys/action アクセス許可を割り当てる必要があります。

注意

ユーザー委任 SAS により、ストレージ アカウント キーで署名された SAS のセキュリティが向上します。 Microsoft では、ユーザー委任 SAS を可能な限り使用することを推奨しています。 詳細については、「Shared Access Signatures (SAS) でデータの制限付きアクセスを付与する」を参照してください。

この記事では、Azure Active Directory (Azure AD) 資格情報を使用して、コンテナー、ディレクトリ、または BLOB のユーザー委任 SAS を、バージョン 12 の .NET 用 Azure Storage クライアント ライブラリで作成する方法について説明します。

ユーザー委任 SAS について

コンテナーまたは BLOB にアクセスするための SAS トークンは、Azure AD 資格情報またはアカウント キーのいずれかを使用してセキュリティ保護することができます。 Azure AD 資格情報でセキュリティ保護された SAS は、ユーザーの代わりに、SAS に署名するために使用される OAuth 2.0 トークンが要求されるため、ユーザー委任 SAS と呼ばれます。

セキュリティのベスト プラクティスとして、より侵害されやすいアカウント キーを使用するのではなく、可能な限り Azure AD 資格情報を使用することをお勧めします。 アプリケーション設計で Shared Access Signature が必要な場合は、セキュリティを強化するために、Azure AD 資格情報を使用してユーザー委任 SAS を作成してください。 ユーザー委任 SAS の詳細については、「ユーザー委任 SAS を作成する」を参照してください。

注意

有効な SAS を所有するすべてのクライアントは、その SAS で許可されているストレージ アカウントのデータにアクセスできます。 SAS を悪意のある、または意図しない用途から保護することが重要です。 SAS の配布は慎重に行い、侵害された SAS を失効させるための計画を用意しておいてください。

Shared Access Signature の詳細については、「Shared Access Signatures (SAS) を使用して Azure Storage リソースへの制限付きアクセスを許可する」を参照してください。

データにアクセスするための Azure ロールを割り当る

Azure AD セキュリティ プリンシパルが Blob データにアクセスしようとする場合、そのセキュリティ プリンシパルはリソースへのアクセス許可を保持している必要があります。 セキュリティ プリンシパルが Azure 内のマネージド ID であるか、開発環境でコードを実行している Azure AD ユーザー アカウントであるかにかかわらず、Azure Storage での BLOB データへのアクセスを許可する Azure ロールをセキュリティ プリンシパルに割り当てる必要があります。 Azure RBAC によるアクセス許可の割り当てについては、「BLOB データにアクセスするために Azure ロールを割り当てる」を参照してください。

Azure Storage から Azure ID クライアント ライブラリを使用してトークンを取得する方法の詳細については、Azure ID ライブラリを使用した認可用のアクセス トークンの取得に関する記事を参照してください。

認証済みのトークン資格情報を取得する

Azure Storage への要求を承認するためにコード上で使用できるトークン資格情報を取得するには、DefaultAzureCredential クラスのインスタンスを作成します。 DefaultAzureCredential クラスを使用し、マネージド ID を認可して Azure Storage にアクセスする方法の詳細については、.NET 用の Azure ID クライアント ライブラリに関する記事を参照してください。

次のコード スニペットでは、認証されたトークン資格情報を取得し、それを使用して Blob ストレージ用のサービス クライアントを作成する方法が示されています。

// Construct the blob endpoint from the account name.
string blobEndpoint = string.Format("https://{0}.blob.core.windows.net", accountName);

// Create a new Blob service client with Azure AD credentials.
BlobServiceClient blobClient = new BlobServiceClient(new Uri(blobEndpoint),
                                                     new DefaultAzureCredential());

ユーザー委任キーを取得する

すべての SAS はキーによって署名されます。 ユーザー委任 SAS を作成するには、まず、SAS に署名するために使用されるユーザー委任キーを要求する必要があります。 ユーザー委任キーは、サービス SAS またはアカウント SAS に署名するために使用されるアカウント キーに似ていますが、Azure AD の資格情報に依存している点が異なります。 クライアントで OAuth 2.0 トークンを使用してユーザー委任キーが要求されると、ユーザーに代わって Azure Storage によってユーザー委任キーが返されます。

ユーザー委任キーを取得したら、そのキーを使用して、キーの有効期間にわたって、任意の数のユーザー委任共有アクセス署名を作成できます。 ユーザー委任キーは、それを取得するために使用された OAuth 2.0 トークンに依存しないため、キーが有効である限り、トークンを更新する必要はありません。 キーの有効期間として、最大 7 日間を指定できます。

ユーザー委任キーを要求するには、次のいずれかの方法を使用します。

次のコード スニペットでは、ユーザー委任キーが取得され、そのプロパティが書き出されます。

// Get a user delegation key for the Blob service that's valid for seven days.
// You can use the key to generate any number of shared access signatures over the lifetime of the key.
UserDelegationKey key = await blobClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                                   DateTimeOffset.UtcNow.AddDays(7));

// Read the key's properties.
Console.WriteLine("User delegation key properties:");
Console.WriteLine("Key signed start: {0}", key.SignedStartsOn);
Console.WriteLine("Key signed expiry: {0}", key.SignedExpiresOn);
Console.WriteLine("Key signed object ID: {0}", key.SignedObjectId);
Console.WriteLine("Key signed tenant ID: {0}", key.SignedTenantId);
Console.WriteLine("Key signed service: {0}", key.SignedService);
Console.WriteLine("Key signed version: {0}", key.SignedVersion);

BLOB 用のユーザー委任 SAS を取得する

次のコード例は、セキュリティ プリンシパルを認証し、BLOB 用のユーザー委任 SAS を作成するためのコード全体を示しています。

async static Task<Uri> GetUserDelegationSasBlob(BlobClient blobClient)
{
    BlobServiceClient blobServiceClient =
        blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient();

    // Get a user delegation key for the Blob service that's valid for 7 days.
    // You can use the key to generate any number of shared access signatures 
    // over the lifetime of the key.
    Azure.Storage.Blobs.Models.UserDelegationKey userDelegationKey =
        await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                          DateTimeOffset.UtcNow.AddDays(7));

    // Create a SAS token that's also valid for 7 days.
    BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = blobClient.BlobContainerName,
        BlobName = blobClient.Name,
        Resource = "b",
        StartsOn = DateTimeOffset.UtcNow,
        ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
    };

    // Specify read and write permissions for the SAS.
    sasBuilder.SetPermissions(BlobSasPermissions.Read |
                              BlobSasPermissions.Write);

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

    Console.WriteLine("Blob user delegation SAS URI: {0}", blobUriBuilder);
    Console.WriteLine();
    return blobUriBuilder.ToUri();
}

次の例では、前の例で作成されたユーザー委任 SAS を、シミュレートされたクライアント アプリケーションからテストします。 SAS が有効であれば、クライアント アプリケーションで BLOB の内容を読み取ることができます。 SAS が無効な場合 (たとえば、有効期限が切れている場合)、Azure Storage によってエラー コード 403 (禁止) が返されます。

static async Task ReadBlobWithSasAsync(Uri sasUri)
{
    // Try performing a read operation using the blob SAS provided.

    // Create a blob client object for blob operations.
    BlobClient blobClient = new BlobClient(sasUri, null);

    // Download and read the contents of the blob.
    try
    {
        Console.WriteLine("Blob contents:");

        // Download blob contents to a stream and read the stream.
        BlobDownloadInfo blobDownloadInfo = await blobClient.DownloadAsync();
        using (StreamReader reader = new StreamReader(blobDownloadInfo.Content, true))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }

        Console.WriteLine();
        Console.WriteLine("Read operation succeeded for SAS {0}", sasUri);
        Console.WriteLine();
    }
    catch (RequestFailedException e)
    {
        // Check for a 403 (Forbidden) error. If the SAS is invalid, 
        // Azure Storage returns this error.
        if (e.Status == 403)
        {
            Console.WriteLine("Read operation failed for SAS {0}", sasUri);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }
        else
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
            throw;
        }
    }
}

コンテナー用のユーザー委任 SAS を取得する

次のコード例は、コンテナー用のユーザー委任 SAS を生成する方法を示しています。

async static Task<Uri> GetUserDelegationSasContainer(BlobContainerClient blobContainerClient)
{
    BlobServiceClient blobServiceClient = blobContainerClient.GetParentBlobServiceClient();

    // Get a user delegation key for the Blob service that's valid for seven days.
    // You can use the key to generate any number of shared access signatures 
    // over the lifetime of the key.
    Azure.Storage.Blobs.Models.UserDelegationKey userDelegationKey =
        await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                          DateTimeOffset.UtcNow.AddDays(7));

    // Create a SAS token that's also valid for seven days.
    BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = blobContainerClient.Name,
        Resource = "c",
        StartsOn = DateTimeOffset.UtcNow,
        ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
    };

    // Specify racwl permissions for the SAS.
    sasBuilder.SetPermissions(
        BlobContainerSasPermissions.Read |
        BlobContainerSasPermissions.Add |
        BlobContainerSasPermissions.Create |
        BlobContainerSasPermissions.Write |
        BlobContainerSasPermissions.List
        );

    // Add the SAS token to the container URI.
    BlobUriBuilder blobUriBuilder = new BlobUriBuilder(blobContainerClient.Uri)
    {
        // Specify the user delegation key.
        Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
                                              blobServiceClient.AccountName)
    };

    Console.WriteLine("Container user delegation SAS URI: {0}", blobUriBuilder);
    Console.WriteLine();
    return blobUriBuilder.ToUri();
}

次の例では、前の例で作成されたユーザー委任 SAS を、シミュレートされたクライアント アプリケーションからテストします。 SAS が有効であれば、クライアント アプリケーションで BLOB の内容を読み取ることができます。 SAS が無効な場合 (たとえば、有効期限が切れている場合)、Azure Storage によってエラー コード 403 (禁止) が返されます。

private static async Task ListBlobsWithSasAsync(Uri sasUri)
{
    // Try performing a listing operation using the container SAS provided.

    // Create a container client object for blob operations.
    BlobContainerClient blobContainerClient = new BlobContainerClient(sasUri, null);

    // List blobs in the container.
    try
    {
        // Call the listing operation and return pages of the specified size.
        var resultSegment = blobContainerClient.GetBlobsAsync().AsPages();

        // Enumerate the blobs returned for each page.
        await foreach (Azure.Page<BlobItem> blobPage in resultSegment)
        {
            foreach (BlobItem blobItem in blobPage.Values)
            {
                Console.WriteLine("Blob name: {0}", blobItem.Name);
            }
            Console.WriteLine();
        }

        Console.WriteLine();
        Console.WriteLine("Blob listing operation succeeded for SAS {0}", sasUri);
    }
    catch (RequestFailedException e)
    {
        // Check for a 403 (Forbidden) error. If the SAS is invalid, 
        // Azure Storage returns this error.
        if (e.Status == 403)
        {
            Console.WriteLine("Blob listing operation failed for SAS {0}", sasUri);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }
        else
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
            throw;
        }
    }
}

ディレクトリ用のユーザー委任 SAS を取得する

次のコード例は、階層型名前空間がストレージ アカウントに対して有効のときに、ディレクトリ用のユーザー委任 SAS を生成する方法を示しています。

async static Task<Uri> GetUserDelegationSasDirectory(DataLakeDirectoryClient directoryClient)
{
    try
    {
        // Get service endpoint from the directory URI.
        DataLakeUriBuilder dataLakeServiceUri = new DataLakeUriBuilder(directoryClient.Uri)
        {
            FileSystemName = null,
            DirectoryOrFilePath = null
        };

        // Get service client.
        DataLakeServiceClient dataLakeServiceClient =
            new DataLakeServiceClient(dataLakeServiceUri.ToUri(),
                                      new DefaultAzureCredential());

        // Get a user delegation key that's valid for seven days.
        // You can use the key to generate any number of shared access signatures 
        // over the lifetime of the key.
        Azure.Storage.Files.DataLake.Models.UserDelegationKey userDelegationKey =
            await dataLakeServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                                  DateTimeOffset.UtcNow.AddDays(7));

        // Create a SAS token that's valid for seven days.
        DataLakeSasBuilder sasBuilder = new DataLakeSasBuilder()
        {
            // Specify the file system name and path, and indicate that
            // the client object points to a directory.
            FileSystemName = directoryClient.FileSystemName,
            Resource = "d",
            IsDirectory = true,
            Path = directoryClient.Path,
            ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
        };

        // Specify racwl permissions for the SAS.
        sasBuilder.SetPermissions(
            DataLakeSasPermissions.Read |
            DataLakeSasPermissions.Add |
            DataLakeSasPermissions.Create |
            DataLakeSasPermissions.Write |
            DataLakeSasPermissions.List
            );

        // Construct the full URI, including the SAS token.
        DataLakeUriBuilder fullUri = new DataLakeUriBuilder(directoryClient.Uri)
        {
            Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
                                                  dataLakeServiceClient.AccountName)
        };

        Console.WriteLine("Directory user delegation SAS URI: {0}", fullUri);
        Console.WriteLine();
        return fullUri.ToUri();
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
        throw;
    }
}

次の例では、前の例で作成されたユーザー委任 SAS を、シミュレートされたクライアント アプリケーションからテストします。 SAS が有効であれば、クライアント アプリケーションでこのディレクトリに対するファイル パスの一覧を表示することができます。 SAS が無効な場合 (たとえば、有効期限が切れている場合)、Azure Storage によってエラー コード 403 (禁止) が返されます。

private static async Task ListFilesPathsWithDirectorySasAsync(Uri sasUri)
{
    // Try performing an operation using the directory SAS provided.

    // Create a directory client object for listing operations.
    DataLakeDirectoryClient dataLakeDirectoryClient = new DataLakeDirectoryClient(sasUri);

    // List file paths in the directory.
    try
    {
        // Call the listing operation and return pages of the specified size.
        var resultSegment = dataLakeDirectoryClient.GetPathsAsync(false, false).AsPages();

        // Enumerate the file paths returned with each page.
        await foreach (Page<PathItem> pathPage in resultSegment)
        {
            foreach (PathItem pathItem in pathPage.Values)
            {
                Console.WriteLine("File name: {0}", pathItem.Name);
            }
            Console.WriteLine();
        }

        Console.WriteLine();
        Console.WriteLine("Directory listing operation succeeded for SAS {0}", sasUri);
    }
    catch (RequestFailedException e)
    {
        // Check for a 403 (Forbidden) error. If the SAS is invalid, 
        // Azure Storage returns this error.
        if (e.Status == 403)
        {
            Console.WriteLine("Directory listing operation failed for SAS {0}", sasUri);
            Console.WriteLine("Additional error information: " + e.Message);
            Console.WriteLine();
        }
        else
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
            throw;
        }
    }
}

.NET で開発するためのリソース

次のリンクからは、.NET 用の Azure Storage クライアントライブラリを使用する開発者にとって役立つリソースが提供されます。

Azure Storage 共通 API

BLOB ストレージ API

.NET ツール

関連項目