Databricksオートメーションのためのサービスプリンシパル

[Service principals for Databricks automation \| Databricks on AWS](https://docs.databricks.com/dev-tools/service-principals.html) [2022/7/8時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

[サービスプリンシパル](https://docs.databricks.com/administration-guide/users-groups/service-principals.html)はスクリプト、アプリケーション、CI/CDプラットフォームのような自動化ツール、自動化システムで使用するために作成されるアイデンティティです。

セキュリティのベストプラクティスとして、自動化ツールやサービスにDatabricksリソースへのアクセスを許可する際、DatabricksユーザーやあなたのワークスペースのDatabricksアクセストークンではなく、DatabricksのサービスプリンシパルとDatabricksアクセストークンを使用することをお勧めします。このアプローチには以下のメリットがあります。

- ユーザーと独立したDatabricksサービスプリンシパルにDatabricksリソースへのアクセスを許可、制限することができます。例えば、Databricksサービスプリンシパルがお使いのDatabricksワークスペースの管理者として振る舞うことを禁止しつつも、特定の他のユーザーは管理者としてあり続けられるようにできます。
- 自動化ツールやシステムによる自分のアクセストークンへのアクセスを防御することができます。
- 他のユーザーに影響を与えることなしに、Databricksサービスプリンシパルを一時的に無効化、あるいは恒久的に削除することができます。例えば、これによって、不正な方法で使用していると疑わしいDatabricksサービスプリンシパルからのアクセスを停止、削除することができます。
- ユーザーが皆様の組織を去った際、いかなるDatabricksサービスプリンシパルに影響を与えることなしにそのユーザーを削除することができます。

Databricksサービスプリンシパルを作成するには、以下のツールやAPIを使用します。

- [SCIM API 2\.0 \(ServicePrincipals\)](https://docs.databricks.com/dev-tools/api/latest/scim/scim-sp.html)を用いて、ワークスペース上にDatabricksサービスプリンシパルを作成します。
- [Token Management API 2\.0](https://docs.databricks.com/dev-tools/api/latest/token-management.html)を用いてDatabricksサービスプリンシパルのDatabricksアクセストークンを作成します。

これらのAPIを呼び出すために、`curl`やPostmanのようなツールを利用できます。Databricksユーザーインタフェースを使うことはできません。

本書では以下を説明します。

1. DatabricksワークスペースでDatabricksサービスプリンシパルを作成する方法
1. Databricksサービスプリンシパル向けのDatabricksアクセストークンを作成する方法

# 要件

- あなたのDatabricksワークスペースユーザーのDatabricks[パーソナルアクセストークン](https://docs.databricks.com/dev-tools/api/latest/authentication.html#token-management)。これによってDatabricks APIを呼び出せるようになります。 
- [curl](https://curl.se/)や[Postman](https://www.postman.com/downloads)のようなDatabricks APIを呼び出すためのツール。

PostmanでDatabricks APIを呼び出す際には、本文の例のように[ワークスペースのインスタンス名](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)、例えば`dbc-a1b2345c-d6e7.cloud.databricks.com`やワークスペースユーザーのDatabriksパーソナルアクセストークンを入力するのではなく、Postmanで[変数を定義](https://learning.postman.com/docs/sending-requests/variables/#defining-variables)し、[利用](https://learning.postman.com/docs/sending-requests/variables/#using-variables)することもできることに注意してください。

`curl`を用いてDatabricks APIを呼び出す場合、本書の`curl`のサンプルでは、お使いのDatabricksワークスペースのインスタンスURL、例えば`https://dbc-a1b2345c-d6e7.cloud.databricks.com`とワークスペースユーザーのDatabricksパーソナルアクセストークンを表す環境変数`DATABRICKS_HOST`と`DATABRICKS_TOKEN`を使用しています。これらの環境変数を設定するには、以下の操作を行なってください。

## Unix、Linux、macOS

現在のターミナルセッションのみの環境変数を設定するには、以下のコマンドを実行します。すべてのターミナルセッションの環境変数を設定するには、シェルのスタートアップファイルに以下のコマンドを入力し、ターミナルを再起動します。サンプルの値をご自身の環境の値で置き換えてください。

```sh
export DATABRICKS_HOST="https://dbc-a1b2345c-d6e78.cloud.databricks.com"
export DATABRICKS_TOKEN="dapi1234567890b2cd34ef5a67bc8de90fa12b"
```

## Windows

現在のコマンドプロンプトセッションのみの環境変数を設定するには、以下のコマンドを実行してください。サンプルの値をご自身の環境の値で置き換えてください。

```shell
set DATABRICKS_HOST="https://dbc-a1b2345c-d6e78.cloud.databricks.com"
set DATABRICKS_TOKEN="dapi1234567890b2cd34ef5a67bc8de90fa12b"
```

すべてのコマンドプロンプトのセッションの環境変数を設定するには、以下のコマンドを実行しコマンドプロンプトを再起動してください。サンプルの値をご自身の環境の値で置き換えてください。

```shell
setx DATABRICKS_HOST "https://dbc-a1b2345c-d6e78.cloud.databricks.com"
setx DATABRICKS_TOKEN "dapi1234567890b2cd34ef5a67bc8de90fa12b"
```

`curl`でDatabricks APIを呼び出す際には、以下のことにも注意してください。

- 本書の`curl`のサンプルではUnix、Linux、macOSフォーマットを使用しています。Windowsのコマンドシェルでは、`\`を`^`、`${...}`を`%...%`で置き換えてください。
- `curl`の結果を読みやすくするために、JSONフォーマットの出力を整形する[jq](https://stedolan.github.io/jq)のようなツールを使用することができます。本書の`curl`サンプルでは、JSON出力をフォーマッティングするために`jq`を使用しています。
- 複数のワークスペースを操作する際、`DATABRICKS_HOST`や`DATABRICKS_TOKEN`を変更し続けるのではなく、[\.netrc](https://docs.databricks.com/dev-tools/api/latest/authentication.html#netrc)ファイルを使用することができます。`.netrc`ファイルを使っている場合には、以下のように本書の`curl`サンプルを変更してください。

    - `curl -X`を`curl --netrc -X`に変更します。
    - `${DATABRICKS_HOST}`をお使いのDatabricks[ワークスペースインスタンスURL](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)、例えば`https://dbc-a1b2345c-d6e7.cloud.databricks.com`に置き換えます。
    - `--header "Authorization: Bearer ${DATABRICKS_TOKEN}" \`を削除します。

# Databricksサービスプリンシパルの作成

すでにDatabricksサービスプリンシパルがある場合には、DatabricksサービスプリンシパルのためのDatabricksアクセストークンを作成するために次のセクションにスキップしてください。

DatabricksワークスペースにDatabricksサービスプリンシパルを追加するために、`curl`やPostmanのようなツールを使うことができます。以下の指示では、下の置き換えを行なってください。

- `<display-name>`をDatabricksサービスプリンシパルの表示名で置き換えてください。
- `entitlements`の配列を、Databricksサービスプリンシパルに追加する任意の[エンタイトルメント](https://docs.databricks.com/administration-guide/users-groups/service-principals.html#manage-entitlements-for-a-service-principal)で置き換えてください。このサンプルでは、Databricksサービスプリンシパルにクラスターを作成する権限を許可します。DatabricksサービスプリンシパルにはデフォルトでワークスペースへのアクセスとDatabricks SQLへのアクセスが許可されています。
- `<group-id>`をDatabricksサービスプリンシパルを属させたいDatabricksワークスペースのグループIDで置き換えてください。(それぞれのDatabricksサービスプリンシパルではなく、グループにアクセス権を設定する方が容易です)
    - グループを追加するには、`groups`配列にグループIDを追加します。
    - グループIDを取得するには[Get groups](https://docs.databricks.com/dev-tools/api/latest/scim/scim-groups.html#get-groups)を呼び出します。
    - グループを作成するには、ユーザーインタフェースで[グループを追加](https://qiita.com/taka_yayoi/items/cf910645f7b7420e58e4#%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%81%AE%E8%BF%BD%E5%8A%A0)するか、[Create group](https://docs.databricks.com/dev-tools/api/latest/scim/scim-groups.html#create-group) APIをコールします。
    - グループにアクセス権を追加するには、ユーザーインタフェースのオプションの[Manage workspace\-level groups](https://docs.databricks.com/administration-guide/users-groups/groups.html)をご覧いただくか、[Permissions API 2\.0](https://docs.databricks.com/dev-tools/api/latest/permissions.html)を呼び出してください。
    - Databricksサービスプリンシパルがグループに属さないようにするには、`groups`配列を削除します。

## Curl

以下のコマンドを実行します。`create-service-principal.json`がコマンドを実行する場所と同じディレクトリに存在するようにしてください。

DatabricksサービスプリンシパルのDatabricksアクセストークンを作成する際に必要になるので、コマンドのアウトプットの`applicationId`の値をコピーしておきます。

```sh
curl -X POST \
${DATABRICKS_HOST}/api/2.0/preview/scim/v2/ServicePrincipals \
--header "Content-type: application/scim+json" \
--header "Authorization: Bearer ${DATABRICKS_TOKEN}" \
--data @create-service-principal.json \
| jq .
```

```json:create-service-principal.json
{
  "displayName": "<display-name>",
  "entitlements": [
    {
      "value": "allow-cluster-create"
    }
  ],
  "groups": [
    {
      "value": "<group-id>"
    }
  ],
  "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:ServicePrincipal" ],
  "active": true
}
```

## Postman

1. 新規HTTPリクエストを作成します(**File > New > HTTP Request**)。
1. HTTP verbドロップダウンリストで**POST**を選択します。
1. **Enter request URL**に`https://<databricks-instance-name>/api/2.0/preview/scim/v2/ServicePrincipals`を入力します。ここでは、`<databricks-instance-name>`は、`dbc-a1b2345c-d6e7.cloud.databricks.com`のようなお使いのDatabricks[ワークスペースインスタンス名](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)です。
1. **Authorization**タブの**Type**リストで**Bearer Token**を選択します。
1. **Token**には、あなたのDatabricksユーザーのDatabricksパーソナルアクセストークンを入力します。
1. **Headers**タブで`Content-Type`と`application/scim+json`の**Key**と**Value**のペアを追加します。
1. **Body**タブで**raw**と**JSON**を選択します。
1. 以下のbodyペイロードを入力します。

    ```json:JSON
    {
      "displayName": "<display-name>",
      "entitlements": [
        {
          "value": "allow-cluster-create"
        }
      ],
      "groups": [
        {
          "value": "<group-id>"
        }
      ],
      "schemas": [ "urn:ietf:params:scim:schemas:core:2.0:ServicePrincipal" ],
      "active": true
    }
    ```

1. **Send**をクリックします。
1. DatabricksサービスプリンシパルのDatabricksアクセストークンを作成する際に必要になるので、responseペイロードの`applicationId`の値をコピーしておきます。


# Databricksサービスプリンシパル向けのDatabricksアクセストークンの作成

## ステップ1: DatabricksサービスプリンシパルのIDの取得

すでにDatabricksサービスプリンシパルのIDを取得しているのであればステップ2にスキップしてください。

DatabricksサービスプリンシパルのIDを取得するために、`curl`やPostmanのようなツールを使うことができます。IDを取得するには以下を実行します。

### Curl

以下のコマンドを実行します。コマンドのアウトプットでDatabricksサービスプリンシパルの`applicationId`をコピーします。

```sh
curl -X GET \
${DATABRICKS_HOST}/api/2.0/preview/scim/v2/ServicePrincipals \
--header "Authorization: Bearer ${DATABRICKS_TOKEN}" \
| jq .
```

### Postman

1. 新規HTTPリクエストを作成します(**File > New > HTTP Request**)。
1. HTTP verbドロップダウンリストで**GET**を選択します。
1. **Enter request URL**に`https://<databricks-instance-name>/api/2.0/preview/scim/v2/ServicePrincipals`を入力します。ここでは、`<databricks-instance-name>`は、`dbc-a1b2345c-d6e7.cloud.databricks.com`のようなお使いのDatabricks[ワークスペースインスタンス名](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)です。
1. **Authorization**タブの**Type**リストで**Bearer Token**を選択します。
1. **Token**には、あなたのDatabricksユーザーのDatabricksパーソナルアクセストークンを入力します。
1. **Send**をクリックします。
1. responseペイロードでDatabricksサービスプリンシパルの`applicationId`をコピーします。

## ステップ2: Databricksサービスプリンシパル向けのDatabricksアクセストークンの作成

DatabricksサービスプリンシパルのDatabricksアクセストークンを作成するために`curl`かPostmanを使うことができます。以下の手順では下の置き換えを行なってください。

- `<application-id>`をDatabricksサービスプリンシパルの`applicationId`で置き換えてください。
- `<comment>`を任意のDatabricksアクセストークンのコメントで置き換えてください。コメントを追加しない場合には、`comment`オブジェクトを削除してください。
- `1209600`をDatabricksアクセストークンの有効期限の秒数で置き換えてください。この例では14日を指定しています。

:::note warn
**重要！**
上の時間を経過すると、このDatabricksアクセストークンは無効化され、このDatabricksアクセストークンに依存しているいかなるCI/CDプラットフォームは動作しなくなります。このような状況を回避するためには、有効期限が切れる前に新たなDatabricksアクセストークンを作成し、CI/CDプラットフォームに割り当てる必要があります。
:::

### Curl

以下のコマンドを実行します。`create-service-principal-token.json`がコマンドを実行する場所と同じディレクトリに存在するようにしてください。

CI/CDプラットフォームのセットアップに必要になるので、コマンドの出力から`token_value`の値をコピーしておきます。

:::note info
**注意**
アクセスが拒否されたメッセージを受け取る場合には、DatabricksサービスプリンシパルにDatabricksアクセストークンの使用を許可する**Can Use**権限を許可するために、[Manage token permissions using the admin console](https://docs.databricks.com/administration-guide/access-control/tokens.html#manage-token-permissions-using-the-admin-console)をご覧ください。
:::

```sh
curl -X POST \
${DATABRICKS_HOST}/api/2.0/token-management/on-behalf-of/tokens \
--header "Content-type: application/json" \
--header "Authorization: Bearer ${DATABRICKS_TOKEN}" \
--data @create-service-principal-token.json \
| jq .
```

```json:create-service-principal-token.json
{
  "application_id": "<application-id>",
  "comment": "<comment>",
  "lifetime_seconds": 1209600
}
```

### Postman

1. 新規HTTPリクエストを作成します(**File > New > HTTP Request**)。
1. HTTP verbドロップダウンリストで**POST**を選択します。
1. **Enter request URL**に`https://<databricks-instance-name>/api/2.0/token-management/on-behalf-of/tokens`を入力します。ここでは、`<databricks-instance-name>`は、`dbc-a1b2345c-d6e7.cloud.databricks.com`のようなお使いのDatabricks[ワークスペースインスタンス名](https://qiita.com/taka_yayoi/items/7127cabac70dd994fcba#%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E5%90%8Durlid)です。
1. **Authorization**タブの**Type**リストで**Bearer Token**を選択します。
1. **Token**には、あなたのDatabricksユーザーのDatabricksパーソナルアクセストークンを入力します。
1. **Headers**タブで`Content-Type`と`application/scim+json`の**Key**と**Value**のペアを追加します。
1. **Body**タブで**raw**と**JSON**を選択します。
1. 以下のbodyペイロードを入力します。

    ```json:JSON
    {
      "application_id": "<application-id>",
      "comment": "<comment>",
      "lifetime_seconds": 1209600
    }
    ```

1. **Send**をクリックします。
1. CI/CDプラットフォームのセットアップに必要になるので、responsペイロードから`token_value`の値をコピーしておきます。

:::note info
**注意**
アクセスが拒否されたメッセージを受け取る場合には、DatabricksサービスプリンシパルにDatabricksアクセストークンの使用を許可する**Can Use**権限を許可するために、[Manage token permissions using the admin console](https://docs.databricks.com/administration-guide/access-control/tokens.html#manage-token-permissions-using-the-admin-console)をご覧ください。その後に再度**Send**をクリックしてください。
:::

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)