README.md

Azure Data Lake StorageのContainerレベルでのアクセス制御

Databricksにおいて、 Azure Data Lake Storage(blob store, 以下ADLS)のContainerレベルでのアクセス制御を 実装する方法について説明します。

注意 ここで説明する方法はAzure DatabricksのPremiumプランが必要になります。Standardプランでは実施できません。

本記事での要件は、以下の通りです。

  • 一つのADLSのStorage Account内に複数のContainerが存在する
  • それぞれのContainerにアクセスできるグループを限定したい
  • ユーザーはいくつかのグループに所属している
  • 所属するグループするユーザーは、グループが許可されているADLS Containerにアクセスできる
  • それ以外のADLS Containerにはアクセスは許可しない
  • ユーザー追加・削除、そのユーザーのグループへの参加・脱退がある程度頻繁に発生する

下図にある構成により、上記の要件を満たすための連携方式を設定していきます。

設定のステップは以下の通りです。

  1. ADLS StorageおよびContainerを作成する(既存のものを使用する場合、本ステップは不要)
  2. Service Principalを作成する
  3. ADLS ContainerのIAMで、"ストレージ BLOB データ共同作成者"ロールに上記のService Principalを追加する
  4. Service Principalの"クライアントシークレット"を新規発行する
  5. Databricksのユーザーグループを作成する
  6. DatabricksのSecrets機能で、新規にSecret Scopeを作成・設定する
    1. 上記のService Principalの"クライアントシークレット"の値を作成したSecret Scopeに登録する
    2. 上記のユーザーグループからこのSecret Scopeへのアクセスを許可する
  7. ユーザーグループに所属するユーザーを設定(追加・削除)
  8. 各ユーザーでSparkパラメータの設定を実行する
    • 方法1: 毎回、Notebook上で実行する
    • 方法2: クラスタ起動時に設定する

上記は初期設定時のステップになります。ユーザーの追加・削除の際は、最後のステップの操作のみで可能です。

以下、それぞれのステップを見ていきます。

注意 ここで説明する方法は、Service Principalに割り当てるRoleの範囲をStorage Containerレベルで使用することで、Containerレベルのアクセス制御の分離をしています。このRoleの範囲をStorage Accountレベルにすることで、同様の方法でStorage Accountごとのアクセス制御が可能になります。

Service Principalを作成する

Azure Portalから、

  1. => Azure Active Directory
  2. => メニュー上部の"+追加"
  3. => "アプリの登録"
  4. => "名前"にService Principlaの名前を入力(適宜): この例ではdbjp-sp-groupAを使用する
  5. => "登録"をクリック

以上で、Service Pricipalが作成できました。

ADLS ContainerのIAMで、"ストレージ BLOB データ共同作成者"ロールに上記のService Principal追加する

Azure Portalから

  1. => Storage Accountで対象のストレージアカウントの管理画面に入る
  2. => 対象のコンテナーを選択し、管理画面に移動する
  3. => コンテナー管理画面(ストレージアカウント管理画面ではない!)の左メニュ"アクセス制御(IAM)"をクリック
  4. => 上部メニューの"+追加"から、"ロールの割り当て追加"
  5. => 以下の通り選択・設定する
    • ロール: "ストレージ BLOB データ共同作成者"
    • メンバー("+メンバーを選択する"から): 前ステップで作成したService Principal(この例では dbjp-sp-groupA)を選択
    • 最後まで進み、"レビューと作成"

以上で、コンテナーとService Principalの関連づけが完了しました。

Service Principalの"クライアントシークレット"を新規発行する

Azure Portalから

  1. => Azure Active Directory
  2. => 左メニュの"アプリの登録"
  3. => アプリケーションリストから前ステップで作成したService Principal(dbjp-sp-groupA)の管理画面に入る
  4. => 左メニューの"証明書とシークレット"
  5. => "+新しいクライアントシークレット"
  6. => "説明"と"有効期限"を適宜設定し、"追加"
  7. => シークレットの"値"をメモしておく(後ほどDatabricksのSecretsにこの値を登録する)

以上でクライアントシークレットの準備ができました。

Databricksのユーザーグループを作成する

  1. => Azure DatabricksにAdminユーザーでログインする
  2. => 左メニューの"Settings" > "Admin Console"
  3. => Admin Consle上部の"Groups"タブ
  4. => "+Create Group"からグループを作成する(ここでは例としてteam-Aというグループを作成する)

以上でユーザーグループが作成できました。

DatabricksのSecrets機能で、新規にSecret Scopeを作成・設定する

DatabricksのSecrets機能を設定するには、Databricks CLIおよびAccess Tokenの設定が必要になります。SecretsおよびDatabricks CLIの設定方法は以下の記事を参照ください。

Databricks CLIおよびSecretsの使い方

以降では既にCLIが使用できる前提で進めます。

上記のService Principalの"クライアントシークレット"の値を作成したSecret Scopeに登録する

以下の通りのSecretsを作成・設定していきます。

  • Secret Scope: secrets_scope_teamA
    • Secret #1:
      • key => adls_sp_secret
      • valu e=> "Service Principalのシークレット値" (この例ではEJd7Q~mQE8X3WO6A4tbjGNzBYZWqMoHd-PY3c)

CLIを実行できるTerminal上で以下のコマンドを実行します。

### Secrets Scopeの作成
$ databricks secrets create-scope --scope "secrets_scope_teamA"

### Service Principalのシークレット値を登録する
$ databricks secrets put --scope "secrets_scope_teamA" \
    --key "adls_sp_secret" \
    --string-value "EJd7Q~mQE8X3WO6A4tbjGNzBYZWqMoHd-PY3c"

### Scopeの確認
$ databricks secrets list-scopes

Scope                Backend         KeyVault URL
-------------------  --------------  -----------------------------------
secrets_scope_teamA  DATABRICKS      N/A


### Secrets登録の確認
$ databricks secrets list --scope "secrets_scope_teamA"

Key name          Last updated
--------------  --------------
adls_sp_secret   1636267297403

以上でService Principalのシークレット値をDatabricks Secretsに登録できました。

上記のユーザーグループからこのSecret Scopeへのアクセスを許可する

同様にCLIが実行できるTerminal上で以下のコマンドを実行します。

### グループ"team-A"に対して`READ`権限を付与する
$ databricks secrets put-acl --scope "secrets_scope_teamA" --principal team-A --permission READ

### 確認
$ databricks secrets list-acls --scope "secrets_scope_teamA" 

Principal                         Permission
--------------------------------  ------------
team-A                            READ
admin-user-foobar@example123.com  MANAGE

以上でSecretsがグループ内のユーザーから参照することが可能になりました。

ユーザーグループに所属するユーザーを設定(追加・削除)

  1. => Azure DatabricksにAdminユーザーでログインする
  2. => Azure DatabricksにAdminユーザーでログインする
  3. => 左メニューの"Settings" > "Admin Console"
  4. => Admin Consle上部の"Groups"タブから対象のグループ管理画面に入る(この例ではteam-A)
  5. => "Members"タブ内の"+ Add users, groups, or service principals"からグループにユーザーを追加する(または削除する)

以上で、ユーザーのグループへの追加・削除は完了しました。

各ユーザーでSparkパラメータの設定を実行する

方法1: 毎回、Notebook上で実行する

Notebook上で以下のコードを実行します。 設定するパラメータ変数は以下の通りです。

  • storage_account: ADLSのStorage Account名
  • storage_countainer: ADLSのコンテナ名
  • application_id: Service PrincipalのApplication ID(下記参照)
  • directory_id: Service PrincipalのDirectory ID(下記参照)
    • Application ID, Directory IDはService Principalの管理画面から確認できます。
  • secrets_scope: Databricks SecretsのScope名
  • secret_key: Databricks Secretsのシークレットkey名

これらのパラメータ値について、今回の例では以下の通りになります。

[Databricks Notebook上]
%python

# パラメータ設定(適宜書き換えてください)
storage_account = 'dbjpstorageaccount'
storage_container = 'container00aaa'

application_id = '39a6c323-40d4-4e48-9b36-dbb27fedf3ef'
directory_id = '9f37a392-f0ae-4280-9796-f1864a10effc'

secrets_scope = 'secrets_scope_teamA'
secret_key = 'adls_sp_secret'


# 以下はそのまま実行(書き換え不要)
spark.conf.set(f'fs.azure.account.auth.type.{storage_account}.dfs.core.windows.net', 'OAuth')
spark.conf.set(f'fs.azure.account.oauth.provider.type.{storage_account}.dfs.core.windows.net', 'org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider')
spark.conf.set(f'fs.azure.account.oauth2.client.id.{storage_account}.dfs.core.windows.net', application_id)
spark.conf.set(f'fs.azure.account.oauth2.client.secret.{storage_account}.dfs.core.windows.net', dbutils.secrets.get(scope=secrets_scope, key=secret_key))
spark.conf.set(f'fs.azure.account.oauth2.client.endpoint.{storage_account}.dfs.core.windows.net', f'https://login.microsoftonline.com/{directory_id}/oauth2/token')

上記の設定の元、ADLSのコンテナーには以下のパスでアクセスできます。

abfss://{storage_container}@{storage_account}.dfs.core.windows.net/

アクセスできるか確認します。

[Databricks Notebook上]
%python

storage_account = 'dbjpstorageaccount'
storage_container = 'container00aaa'

display(
  dbutils.fs.ls(f'abfss://{storage_container}@{storage_account}.dfs.core.windows.net/')
)

方法2: クラスタ起動時に設定する

Databricksのクラスタ設定で以下のSparkパラメータを設定しておきます。 (<storage-account-name>, <application-id>, <directory-id>を適宜書き換えてください)

SparkパラメータのUI上からSecretsを参照するには{{secrets/<secret_scope>/<secrets_key>}}の形式で可能です。今回の例では{{secrets/secrets_scope_teamA/adls_sp_secret}}になります。

注意 クラスタを起動するユーザーがSecrets Scopeにアクセスできる必要があります。

spark.hadoop.fs.azure.account.auth.type.<storage-account-name>.dfs.core.windows.net OAuth
spark.hadoop.fs.azure.account.oauth.provider.type.<storage-account-name>.dfs.core.windows.net org.apache.hadoop.fs.azurebfs.oauth2.ClientCredsTokenProvider
spark.hadoop.fs.azure.account.oauth2.client.id.<storage-account-name>.dfs.core.windows.net <application-id>
spark.hadoop.fs.azure.account.oauth2.client.secret.<storage-account-name>.dfs.core.windows.net {{secrets/secrets_scope_teamA/adls_sp_secret}}
spark.hadoop.fs.azure.account.oauth2.client.endpoint.<storage-account-name>.dfs.core.windows.net https://login.microsoftonline.com/<directory-id>/oauth2/token

先ほどと同様にアクセスできるか確認します。

参考リンク