アカウントキーを相手へ渡さず、Azure Blob Storage上の特定ファイルだけを短期間ダウンロードさせるなら、Azure CLIでユーザー委任SASを生成する方法が適しています。
--nameで対象Blobを限定し、--permissions rで読み取りだけを許可し、--expiryで有効期限を設定します。さらに、--auth-mode login --as-userを指定すれば、ストレージアカウントキーではなくMicrosoft Entraの資格情報を使ってSASを署名できます。
ただし、ユーザー委任SASも「URLを知っている人に、指定した権限を与える仕組み」である点は変わりません。生成したURLはパスワードと同じように扱い、短い期限を設定して安全な経路で渡す必要があります。([Microsoft Learn][1])
Azure Blobの期限付きダウンロードにユーザー委任SASが向く理由
Azure Blob Storageのデータを共有するために、ストレージアカウントキーや接続文字列を相手へ渡すべきではありません。
アカウントキーはストレージアカウント全体に関係する強力な秘密情報です。一方、ユーザー委任SASでは、次の項目を限定できます。
| 限定する項目 | Azure CLIでの指定例 |
|---|---|
| ストレージアカウント | --account-name |
| コンテナー | --container-name |
| 特定のBlob | --name |
| 許可する操作 | --permissions r |
| 有効期限 | --expiry |
| 通信方法 | --https-only |
ユーザー委任SASはMicrosoft Entraの資格情報を基に生成されます。アカウントキーをアプリや担当者へ配布せずに済むため、SASが必要な場合は、アカウントキーで署名するSASよりもユーザー委任SASが推奨されています。([Microsoft Learn][1])
なお、共有先の利用者にMicrosoft Entraアカウントは必須ではありません。通常のユーザー委任SASでは、有効なSAS URLを持っているクライアントが、URLに設定された範囲でBlobへアクセスできます。
そのため、ユーザー委任SASは次のような用途に向いています。
- 取引先へPDFを1時間だけダウンロード可能にする
- 一時的な成果物を外部担当者へ渡す
- サポート対象者にログファイルを短時間だけ提供する
- Blobを一般公開せず、特定ファイルだけを共有する
継続的に同じ利用者へアクセスさせる場合は、SASを繰り返し発行するよりも、Microsoft Entra IDとAzure RBACによるアクセス制御を検討した方が管理しやすいことがあります。
最初に確認する2種類の権限
ユーザー委任SASを生成する担当者には、次の2種類の権限が必要です。
| 権限 | 用途 |
|---|---|
| ユーザー委任キーを生成する権限 | Microsoft Entraの資格情報を使ってSASへ署名する |
| Blobデータへアクセスする権限 | SASで相手に許可する読み取りなどの操作を実行可能にする |
ユーザー委任キーを生成する権限
SASを発行するMicrosoft Entraのセキュリティプリンシパルには、次のアクションを含むAzure RBACロールが必要です。
Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action
このアクションはストレージアカウント単位で実行されるため、ロールは次のいずれかのスコープで割り当てます。
- ストレージアカウント
- リソースグループ
- サブスクリプション
Microsoft Learnでは、Storage Blob Data Reader、Storage Blob Data Contributor、Storage Blob Data Owner、Storage Blob Delegatorなどが、ユーザー委任キーの生成に必要なアクションを含む組み込みロールとして挙げられています。([Microsoft Learn][2])
Blobを読み取るデータ権限
ユーザー委任SASで実際に利用できる権限は、次の両方を満たす範囲に限定されます。
- SASを発行した本人がAzure RBACやACLで持っている権限
- SASの
--permissionsで指定した権限
たとえば、SASに--permissions rを指定しても、発行者自身に対象Blobの読み取り権限がなければ、共有先もBlobを読み取れません。反対に、発行者が書き込み権限を持っていても、SASをrだけにすれば、共有先に書き込み権限は与えられません。([Microsoft Learn][2])
最小権限で構成する例
権限を対象コンテナーに限定したい場合は、次のように役割を分ける構成が考えられます。
| ロール | スコープ | 目的 |
|---|---|---|
Storage Blob Delegator | ストレージアカウント | ユーザー委任キーを生成する |
Storage Blob Data Reader | 対象コンテナー | 対象コンテナー内のBlobを読み取る |
より簡単に構成するなら、Storage Blob Data Readerをストレージアカウントへ割り当てる方法もあります。ただし、その担当者はストレージアカウント内の他のコンテナーも読み取れる可能性があるため、管理対象と必要な範囲を確認してからスコープを決めます。
ロールを割り当てる権限がない場合は、ストレージアカウントの管理者へ依頼してください。
Azure CLIで対象テナントへサインインする
Azure CLIをローカル環境で使う場合は、対象のMicrosoft Entraテナントへサインインします。
az login --tenant "<tenant-id>"
複数のサブスクリプションを利用している場合は、対象サブスクリプションを明示します。
az account set --subscription "<subscription-id-or-name>"
現在選択されているサブスクリプションとテナントは、次のコマンドで確認できます。
az account show \
--query "{subscription:name, subscriptionId:id, tenantId:tenantId}" \
--output table
Azure CLIでは、サインイン後のコマンドが既定のサブスクリプションに対して実行されます。別のサブスクリプションを操作する場合は、SAS生成前にaz account setで切り替えておく必要があります。([Microsoft Learn][3])
Azure Cloud Shellを利用している場合は、通常はAzure CLIへのサインインが済んだ状態で開始できます。ただし、対象サブスクリプションが選択されているかは確認してください。
特定Blobの読み取り専用SASを生成する
特定のBlobだけを共有する場合は、az storage blob generate-sasを使用します。
コンテナー全体を対象とするaz storage container generate-sasではありません。共有範囲を1ファイルに絞りたい場合は、必ずBlob用のコマンドを選びます。
PowerShellで1時間有効なSASを生成する例
次の例では、実行時刻から1時間後を有効期限として計算します。過去の日付を固定値で記載していないため、そのまま値を更新し忘れる事故を防げます。
$storageAccount = "mystorageaccount"
$containerName = "private-downloads"
$blobName = "reports/report.pdf"
$expiryUtc = (Get-Date).ToUniversalTime().AddHours(1).ToString("yyyy-MM-ddTHH:mm'Z'")
$sasUrl = az storage blob generate-sas `
--account-name $storageAccount `
--container-name $containerName `
--name $blobName `
--permissions r `
--expiry $expiryUtc `
--auth-mode login `
--as-user `
--https-only `
--full-uri `
--output tsv
生成されたURLを確認する場合は、対話操作中に次を実行します。
$sasUrl
出力されるURLにはSASトークンが含まれます。実際のURLを、記事、ソースコード、Gitリポジトリ、チャットの公開チャンネル、問い合わせ履歴などへ貼り付けないでください。
コマンドの各オプション
| オプション | 意味 |
|---|---|
--account-name | 対象のストレージアカウント |
--container-name | 対象Blobが保存されているコンテナー |
--name | 共有するBlob名。仮想ディレクトリを含む場合はパス全体を指定 |
--permissions r | 読み取りだけを許可 |
--expiry | SASが無効になるUTC日時 |
--auth-mode login | Azure CLIへサインインしたMicrosoft Entra資格情報を使用 |
--as-user | ユーザー委任キーで署名されたSASを生成 |
--https-only | HTTPS通信だけを許可 |
--full-uri | SASトークンを付けた完全なBlob URLを返す |
--output tsv | JSONの引用符を付けず、URL文字列だけを出力 |
--as-userを指定する場合は、--auth-mode loginと--expiryも必要です。--full-uriを付けると、BlobのURLとSASトークンが結合された状態で返されるため、そのまま共有用URLとして扱えます。([Microsoft Learn][4])
--https-onlyを省略すると、CLIの仕様上はHTTPとHTTPSの両方が許可されます。機密性のあるURLを共有する用途では、原則として--https-onlyを付けます。([Microsoft Learn][4])
有効期限はUTCで実行時に計算する
--expiryには、SASが無効になるUTC日時を指定します。
形式は次のようになります。
YYYY-MM-DDTHH:MMZ
固定された日時を記事やスクリプトへ残すと、次に実行したときに過去日付となる可能性があります。PowerShellやシェルで、実行時刻から必要な時間だけ加算する方法が安全です。
運用上の目安は次のとおりです。
| 共有場面 | 有効期間の例 |
|---|---|
| 電話やオンライン会議中の受け渡し | 30分から1時間 |
| 当日中に受け取ってもらう | 4時間から8時間 |
| 時差がある相手への受け渡し | 12時間から24時間 |
| 数日間の作業が必要 | 必要最小限の日数 |
これらはAzureの必須値ではなく、運用設計上の例です。組織のセキュリティポリシーと、受信者が実際にダウンロードできる時間を基準に決めてください。
ユーザー委任キーの有効期間は、開始日時から最大7日です。SASの有効期限に7日を超える日時を指定しても、ユーザー委任キーが期限切れになれば、そのSASは利用できません。7日は推奨値ではなく上限なので、通常のファイル共有では数十分から数時間程度に絞る方が安全です。([Microsoft Learn][1])
読み取り権限だけを指定する
ダウンロードだけを許可したい場合は、次の指定にします。
--permissions r
rは読み取り権限です。Blobの内容に加えて、プロパティやメタデータの読み取りなども対象になりますが、書き込みや削除は許可しません。([Microsoft Learn][2])
一時的なダウンロードURLに、次のような権限を追加する必要は通常ありません。
| 文字 | 主な権限 | ダウンロードだけなら |
|---|---|---|
r | 読み取り | 必要 |
w | 書き込み | 不要 |
c | 作成 | 不要 |
d | 削除 | 不要 |
a | 追加 | 不要 |
公式ドキュメントのサンプルには複数の権限をまとめた例もありますが、ダウンロード専用URLでは、そのままコピーせずrだけに絞ります。
生成したSAS URLを安全に渡す
ユーザー委任SASはアカウントキーではありませんが、URLを持っている人がBlobへアクセスできる秘密情報です。
安全に渡すため、次の点を守ります。
- 公開チャットや共有掲示板へ貼らない
- GitHubなどのリポジトリへ保存しない
- CI/CDの標準出力やデバッグログへ表示しない
- URL短縮サービスへ入力しない
- 不特定多数が閲覧する問い合わせチケットへ貼らない
- 1対1の認証済みチャットなど、受信者を限定できる経路で送る
- 受信者へ有効期限も伝える
SAS URLは長く、?以降に複数のクエリーパラメーターが含まれます。途中で改行されたり、末尾が省略されたりすると利用できません。URL全体を欠けない形で送ります。
コマンドラインからダウンロードする場合は、URL内の&がシェルの制御文字として解釈されないよう、URL全体を引用符で囲みます。
curl --fail --location \
--output "report.pdf" \
"<SAS付きURL>"
実際のSAS URLをコマンド履歴へ残したくない場合は、クリップボードや環境変数から一時的に読み込むなど、利用環境に応じた取り扱いを検討します。
SASを途中で失効させる場合の注意点
ユーザー委任SASには、特定のSASだけを後から選んで無効化できる保存済みアクセスポリシーを設定できません。ユーザー委任SASでは保存済みアクセスポリシーがサポートされていないため、基本的には短い有効期限を最初から設定することが重要です。([Microsoft Learn][1])
緊急時には、次のAzure CLIコマンドで、対象ストレージアカウントのユーザー委任キーを失効させられます。
az storage account revoke-delegation-keys \
--name "<storage-account>" \
--resource-group "<resource-group>"
ただし、この操作は1つのSASだけを無効化するものではありません。
対象ストレージアカウントに関連付けられたすべてのユーザー委任キーが失効し、それらのキーから生成された他のユーザー委任SASも無効になります。複数の部署やシステムが同じストレージアカウントでSASを利用している場合は、影響範囲を確認してから実行してください。([Microsoft Learn][1])
また、ユーザー委任キーやAzureロール割り当てはAzure Storage側でキャッシュされるため、失効操作を実行してから既存SASが利用不能になるまで遅れが生じる場合があります。緊急失効を前提に長期間のSASを配るのではなく、短時間で自然に期限切れになる設計を優先します。([Microsoft Learn][1])
よくある設定ミス
| 設定ミス | 起きる問題 | 対策 |
|---|---|---|
az storage container generate-sasを使う | コンテナー内の複数Blobが対象になり得る | 1ファイルならaz storage blob generate-sasを使う |
--permissionsへ複数権限を付ける | 書き込みや削除まで許可する可能性がある | ダウンロードだけならrのみ |
--as-userを付けない | 意図したユーザー委任SASにならない | --auth-mode login --as-userをセットで指定 |
| 固定された過去日時を使う | 生成直後から利用できない | 実行時刻から期限を動的に計算 |
| ローカル時刻をそのまま指定する | UTCとのずれで期限を誤る | UTCへ変換してZ付きで指定 |
| SAS URLをログへ出力する | ログ閲覧者がBlobへアクセスできる | 出力先とログ設定を確認 |
| URLを引用符で囲まない | &でコマンドが分割される | URL全体を引用符で囲む |
| 失効コマンドを気軽に実行する | 他のユーザー委任SASも停止する | 影響範囲を確認し、原則は短い期限で管理 |
期限付き共有を安全に運用する流れ
実際の運用では、次の順序で確認すると設定漏れを防げます。
- 対象テナントとサブスクリプションへAzure CLIでサインインする
- 発行者にユーザー委任キー生成権限があることを確認する
- 発行者に対象Blobの読み取り権限があることを確認する
--account-name、--container-name、--nameで1つのBlobを指定する--permissions rで読み取りだけに絞る--expiryを実行時刻から必要最小限の時間で計算する--auth-mode login --as-userでユーザー委任SASを生成する--https-only --full-uriで安全に利用できる完全URLを出力する- SAS URLを限定された経路で受信者へ渡す
- 緊急失効は他のSASへの影響を確認してから実行する
アカウントキーを渡さずに特定Blobだけを短期間共有する場合、重要なのは「ユーザー委任SASを使うこと」だけではありません。
発行者の権限、対象Blob、許可操作、有効期限、配布経路、失効時の影響までを一連の設計として考える必要があります。
まずは対象Blobと共有時間を決め、--permissions rと短い--expiryを指定したユーザー委任SASを生成してください。期限を短く保つことが、URLの誤送信や転送が起きた場合の影響を最小限にする最も確実な対策です。
[1]: https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-user-delegation-sas-create-cli “Use Azure CLI to create a user delegation SAS for a container or blob – Azure Storage | Microsoft Learn”
[2]: https://learn.microsoft.com/en-us/rest/api/storageservices/create-user-delegation-sas “Create a user delegation SAS – Azure Storage | Microsoft Learn”
[3]: https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli “Sign in with Azure CLI — Login and Authentication | Microsoft Learn”
[4]: https://learn.microsoft.com/en-us/cli/azure/storage/blob “az storage blob | Microsoft Learn”

コメント