Shared Access Signature(SAS)を使うと、Azure Storage へのアクセス許可を細かく制御できます。しかし、SAS が漏洩すると誰でも Azure Storage にアクセスできてしまう潜在的なリスクがあります。
ユーザー委任 SAS を使うことで、SAS が Azure AD で保護され、コードで SAS を管理する必要がなくなり、漏洩リスクを軽減できます。
docs.microsoft.com
ユースケース
売上分析プラットフォームにおいて、各店舗の POS システムから売上データを収集し、全店舗のデータをまとめた横断的な売上分析を行うシナリオを想定します。
Ingest Layer の Blob Storage に対して、各店舗から売上データ XML ファイルをセキュアにアップロードできるようにします。
gooner.hateblo.jp
RBAC のカスタムロールを作成する
組み込みの Storage Blob Data Contributor では必要以上の権限を与えてしまうので、SAS を生成して Blob Storage にファイルをアップロードのみできるカスタムロール azcopy-role
を作成します。
{ "Name": "azcopy-role", "IsCustom": true, "Description": "", "Actions": [ "Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action" ], "NotActions": [ ], "DataActions": [ "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write", "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/add/action" ], "AssignableScopes": [ "/subscriptions/<サブスクリプションID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Storage/storageAccounts/<ストレージアカウント名>" ] }
Azure Portal でも Storage Blob Data Contributor など組み込みの RBAC を Clone してカスタムロールを作れますが、ここでは Azure CLI を使います。
$ az role definition create --role-definition azcopy-role.json
カスタムロールにサービスプリンシパルを割り当てる
まずは、Azure Portal の Active Directory で App registrations からサービスプリンシパルを作成しておきます。今回は azcopy-user
を作成しました。
$ az ad sp list --display-name "azcopy-user" --query "[].{appId:appId}" [ { "appId": "53c3cd6f-861e-44de-b15a-e1cf2cc5a332" } ]
RBAC には、リソース、リソース グループ、サブスクリプション、管理グループという 4 つのレベルのスコープがあります。必要最低限のアクセス権を付与したいので、ストレージのリソースに対してカスタムロールを割り当てます。
$ az role assignment create --assignee "53c3cd6f-861e-44de-b15a-e1cf2cc5a332" --role "azcopy-role" --scope "/subscriptions/<サブスクリプションID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Storage/storageAccounts/<ストレージアカウント名>"
ユーザー委任 SAS を生成する
ここからは、各店舗側の POS システムで行う作業になります。あらかじめ、サービスプリンシパルのシークレットを作成しておきましょう。
Azure CLI を使って、サービスプリンシパルでログインします。
$ az login --service-principal --username 53c3cd6f-861e-44de-b15a-e1cf2cc5a332 --password <シークレット> --tenant <テナントID>
az storage container generate-sas
コマンドを使って、ユーザー委任 SAS を生成します。指定されたIPアドレスから特定のコンテナへの書き込みのみが許可された SAS が返されます。
$ az storage container generate-sas --account-name <ストレージアカウント名> -n store-a --https-only --permissions c --expiry 2021-03-07T00:00:00Z --ip "176.134.171.0-176.134.171.255" --auth-mode login --as-user
AzCopy でファイルをアップロードする
先ほど生成した SAS を使って、AzCopy で Blob Storage に XML ファイルをアップロードします。
%date:~0,4%/%date:~5,2%/%date:~8,2% は、アップロードを実行した日付のパスにアップロードするための指定です。
$ azcopy cp "*.xml" "https://gooner0102.blob.core.windows.net/store-a/sales/%date:~0,4%/%date:~5,2%/%date:~8,2%?<SAS>"
Blob Storage を確認すると、XML ファイルをアップロードできたことがわかります。
この SAS を使って Blob の一覧を取得しようとしても、403 エラーが返されます。
$ azcopy list "https://gooner0102.blob.core.windows.net/store-a/sales/%date:~0,4%/%date:~5,2%/%date:~8,2%?<SAS>" RESPONSE Status: 403 This request is not authorized to perform this operation using this permission.
ユーザー委任 SAS を取り消す
この SAS が漏洩したことを想定し、az storage account revoke-delegation-keys
コマンドを使って、ユーザー委任 SAS を取り消します。
$ az storage account revoke-delegation-keys --ids /subscriptions/<サブスクリプションID>/resourceGroups/<リソースグループ名>/providers/Microsoft.Storage/storageAccounts/<ストレージアカウント名>
AzCopy でファイルをアップロードしようとしても、403 エラーが返されます。
$ azcopy cp "*.xml" "https://gooner0102.blob.core.windows.net/store-a/sales/%date:~0,4%/%date:~5,2%/%date:~8,2%?<SAS>" RESPONSE Status: 403 Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
まとめ
ユーザー委任 SAS を使って AzCopy で Azure Blob Storage にファイルをアップロードしました。
SAS を使う場合、RBAC のカスタムロールで要件に応じた必要最低限のアクセス権を付与できるので、可能な限りユーザー委任 SAS を使うことを検討しましょう。