Azure Blob Storage と JavaScript を使用してユーザー委任 SAS トークンを作成する
この記事では、JavaScript 用の Azure Blob Storage クライアント ライブラリ v12 でユーザー委任 SAS トークンを作成する方法について説明します。 バージョン 2018-11-09 で導入されたユーザー委任 SAS は、Microsoft Entra 資格情報によってセキュリティで保護され、Blob service では次の場合にのみサポートされます。
- 既存のコンテナーへのアクセス権を付与します。
- BLOB を作成、使用、削除するためのアクセス権を付与します。
ユーザー委任 SAS を作成するには、クライアントに blobServiceClient.getUserDelegationKey 操作を呼び出すアクセス許可が必要です。 この操作によって返されるキーは、ユーザー委任 SAS に署名するために使用されます。 この操作を呼び出すセキュリティ プリンシパルには、Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action を含む RBAC ロールを割り当てる必要があります。
SAS を所有するクライアントに付与されるアクセス許可は、ユーザー委任キーを要求したセキュリティ プリンシパルに付与されたアクセス許可と、署名されたアクセス許可 (sp) フィールドの SAS トークンのリソースに付与されたアクセス許可の共通部分です。 RBAC を介してセキュリティ プリンシパルに付与されたアクセス許可も SAS トークンに付与されていない場合、そのアクセス許可は、SAS を使用してリソースにアクセスしようとするクライアントには付与されません。
実行可能な Node.js ファイルとして GitHub からサンプル コード スニペットを入手できます。
パッケージ (npm) | サンプル | API リファレンス | ライブラリ ソース コード | フィードバックを送る
ユーザー委任 SAS トークンのベスト プラクティス
SAS トークンを持つすべてのユーザーが、それを利用してコンテナーや BLOB にアクセスできるため、最も制限の厳しいアクセス許可で SAS トークンを定義した上で、トークンが必要なタスクを完了できるようにする必要があります。
Azure Cloud で DefaultAzureCredential を使用する
シークレットなしで Azure に対して認証を行うには、マネージド ID を設定します。 このアプローチにより、コードで DefaultAzureCredential を使用できます。
Azure クラウドのマネージド ID を設定するには、次のようにします。
- マネージド ID の作成
- ID に適切なストレージ ロールを設定する
- マネージド ID と連携するように Azure 環境を構成する
これら 2 つのタスクが完了したら、接続文字列またはアカウント キーの代わりに DefaultAzureCredential を使用します。 このアプローチにより、すべての環境でまったく同じソース コードを使用できるようになり、ソース コードでシークレットを使用するという問題がなくなります。
ローカル開発で DefaultAzureCredential を使用する
ローカル開発環境では、ローカル ランタイムとクラウド ランタイムで同じコードを使用するために、Azure ID (Azure portal へのサインインに使用する個人または開発アカウント) を Azure に対して認証する必要があります。
コンテナー: 必要な依存関係をアプリケーションに追加する
コンテナー SAS トークンを作成するために必要な依存関係を含めます。
const {
DefaultAzureCredential
} = require('@azure/identity');
const {
ContainerClient,
BlobServiceClient,
ContainerSASPermissions,
generateBlobSASQueryParameters,
SASProtocol
} = require('@azure/storage-blob');
// used for local environment variables
require('dotenv').config();
コンテナー: 環境変数を取得する
Blob Storage アカウント名とコンテナー名は、コンテナー SAS トークンを作成するために最低限必要な値です。
// Get environment variables for DefaultAzureCredential
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
DefaultAzureCredential を使用して SAS を作成する
DefaultAzureCredential を使用して SAS トークンを作成するには、次の概念的な手順が必要です。
- DefaultAzureCredential を設定する
- ローカル開発 - 個人 ID を使用し、ストレージのロールを設定する
- Azure クラウド - マネージド ID を作成する
- DefaultAzureCredential を使用して UserDelegationKey でユーザー委任キーを取得する
- ユーザー委任キーを使用して、generateBlobSASQueryParameters で適切なフィールドを持つ SAS トークンを作成する
コンテナー: DefaultAzureCredential を使用して SAS トークンを作成する
ID が構成されている場合は、次のコードを使用して、既存のアカウントとコンテナー用のユーザー委任 SAS トークンを作成します。
// Server creates User Delegation SAS Token for container
async function createContainerSas() {
// Get environment variables
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
// Best practice: create time limits
const TEN_MINUTES = 10 * 60 * 1000;
const NOW = new Date();
// Best practice: set start time a little before current time to
// make sure any clock issues are avoided
const TEN_MINUTES_BEFORE_NOW = new Date(NOW.valueOf() - TEN_MINUTES);
const TEN_MINUTES_AFTER_NOW = new Date(NOW.valueOf() + TEN_MINUTES);
// Best practice: use managed identity - DefaultAzureCredential
const blobServiceClient = new BlobServiceClient(
`https://${accountName}.blob.core.windows.net`,
new DefaultAzureCredential()
);
// Best practice: delegation key is time-limited
// When using a user delegation key, container must already exist
const userDelegationKey = await blobServiceClient.getUserDelegationKey(
TEN_MINUTES_BEFORE_NOW,
TEN_MINUTES_AFTER_NOW
);
// Need only list permission to list blobs
const containerPermissionsForAnonymousUser = "l";
// Best practice: SAS options are time-limited
const sasOptions = {
containerName,
permissions: ContainerSASPermissions.parse(containerPermissionsForAnonymousUser),
protocol: SASProtocol.HttpsAndHttp,
startsOn: TEN_MINUTES_BEFORE_NOW,
expiresOn: TEN_MINUTES_AFTER_NOW
};
const sasToken = generateBlobSASQueryParameters(
sasOptions,
userDelegationKey,
accountName
).toString();
return sasToken;
}
上記のサーバー コードは、コンテナー SAS トークンを作成するために値のフローを作成します。
- DefaultAzureCredential を使用して BlobServiceClient を作成する
- blobServiceClient.getUserDelegationKey 操作を使用して UserDelegationKey を作成する
- このキーを使用して、generateBlobSASQueryParameters で SAS トークン文字列を作成する
コンテナー SAS トークンを作成したら、トークンを使用するクライアントにそれを提供できます。 その後、クライアントはそれを使用してコンテナー内の BLOB を一覧表示できます。 クライアント コード例では、SAS をコンシューマーとしてテストする方法を示しています。
コンテナー: SAS トークンを使用する
コンテナー SAS トークンが作成されたら、そのトークンを使用します。 SAS トークンを使用する例として、次の手順を実行します。
- コンテナー名とクエリ文字列を含む完全な URL を作成します。 クエリ文字列は SAS トークンです。
- コンテナー URL を使用して ContainerClient を作成します。
- クライアントを使用します。この例では、listBlobsFlat を使用してコンテナー内の BLOB を一覧表示します。
// Client or another process uses SAS token to use container
async function listBlobs(sasToken){
// Get environment variables
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
// Create Url
// SAS token is the query string with typical `?` delimiter
const sasUrl = `https://${accountName}.blob.core.windows.net/${containerName}?${sasToken}`;
console.log(`\nContainerUrl = ${sasUrl}\n`);
// Create container client from SAS token url
const containerClient = new ContainerClient(sasUrl);
let i = 1;
// List blobs in container
for await (const blob of containerClient.listBlobsFlat()) {
console.log(`Blob ${i++}: ${blob.name}`);
}
}
BLOB: 必要な依存関係をアプリケーションに追加する
BLOB SAS トークンを作成するために必要な依存関係を含めます。
const {
DefaultAzureCredential
} = require('@azure/identity');
const {
BlockBlobClient,
BlobServiceClient,
BlobSASPermissions,
generateBlobSASQueryParameters,
SASProtocol
} = require('@azure/storage-blob');
// used for local environment variables
require('dotenv').config();
BLOB: 環境変数を取得する
Blob Storage アカウント名とコンテナー名は、BLOB SAS トークンを作成するために最低限必要な値です。
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
BLOB SAS トークンを作成する必要がある場合は、SAS トークンを作成するための BLOB 名が必要です。 これは、ランダムな BLOB 名、ユーザーが送信した BLOB 名、アプリケーションから生成された名前など、事前に定義されます。
// Create random blob name for text file
const blobName = `${(0|Math.random()*9e6).toString(36)}.txt`;
BLOB: DefaultAzureCredential を使用して SAS トークンを作成する
ID が構成されている場合は、次のコードを使用して、既存のアカウントとコンテナー用のユーザー委任 SAS トークンを作成します。
// Server creates User Delegation SAS Token for blob
async function createBlobSas(blobName) {
// Get environment variables
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
// Best practice: create time limits
const TEN_MINUTES = 10 * 60 * 1000;
const NOW = new Date();
// Best practice: set start time a little before current time to
// make sure any clock issues are avoided
const TEN_MINUTES_BEFORE_NOW = new Date(NOW.valueOf() - TEN_MINUTES);
const TEN_MINUTES_AFTER_NOW = new Date(NOW.valueOf() + TEN_MINUTES);
// Best practice: use managed identity - DefaultAzureCredential
const blobServiceClient = new BlobServiceClient(
`https://${accountName}.blob.core.windows.net`,
new DefaultAzureCredential()
);
// Best practice: delegation key is time-limited
// When using a user delegation key, container must already exist
const userDelegationKey = await blobServiceClient.getUserDelegationKey(
TEN_MINUTES_BEFORE_NOW,
TEN_MINUTES_AFTER_NOW
);
// Need only create/write permission to upload file
const blobPermissionsForAnonymousUser = "cw"
// Best practice: SAS options are time-limited
const sasOptions = {
blobName,
containerName,
permissions: BlobSASPermissions.parse(blobPermissionsForAnonymousUser),
protocol: SASProtocol.HttpsAndHttp,
startsOn: TEN_MINUTES_BEFORE_NOW,
expiresOn: TEN_MINUTES_AFTER_NOW
};
const sasToken = generateBlobSASQueryParameters(
sasOptions,
userDelegationKey,
accountName
).toString();
return sasToken;
}
上記のコードは、コンテナー SAS トークンを作成するために値のフローを作成します。
- DefaultAzureCredential を使用して BlobServiceClient を作成する
- blobServiceClient.getUserDelegationKey 操作を使用して UserDelegationKey を作成する
- このキーを使用して、SAS トークン文字列を作成します。 BLOB 名がオプションで指定されていない場合、SAS トークンはコンテナー トークンです。
BLOB SAS トークンを作成したら、トークンを使用するクライアントにそれを提供できます。 その後、クライアントはそれを使用して BLOB をアップロードできます。 クライアント コード例では、SAS をコンシューマーとしてテストする方法を示しています。
BLOB: SAS トークンを使用する
BLOB SAS トークンが作成されたら、そのトークンを使用します。 SAS トークンを使用する例として、次の手順を実行します。
- コンテナー名、BLOB 名、クエリ文字列を含む完全な URL を作成します。 クエリ文字列は SAS トークンです。
- コンテナー URL を使用して BlockBlobClient を作成します。
- クライアントの使用: この例では、upload で BLOB をアップロードします。
// Client or another process uses SAS token to upload content to blob
async function uploadStringToBlob(blobName, sasToken, textAsString){
// Get environment variables
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
// Create Url SAS token as query string with typical `?` delimiter
const sasUrl = `https://${accountName}.blob.core.windows.net/${containerName}/${blobName}?${sasToken}`;
console.log(`\nBlobUrl = ${sasUrl}\n`);
// Create blob client from SAS token url
const blockBlobClient = new BlockBlobClient(sasUrl);
// Upload string
await blockBlobClient.upload(textAsString, textAsString.length, undefined);
}