Databricks にて JDBC によりテーブルを参照する際に必要な権限に関する検証

## 概要

Databricks にて BigQuery から JDBC によりテーブルを参照する際に必要となる Google Cloud の権限に関する検証結果を共有します。検証の結果、下記の権限が必要となります。

- BigQuery Data Viewer
- BigQuery Job User
- BigQuery Read Session User（4 万レコード以上の場合）


Databricks Federation を実施際の動作も確認します。Databricks Runtime 16.1 以降のクラスターでは Spark Connector が利用される仕様変更がされたため、 16.4 と 15.4 のバージョンでそれぞれ実行しています。仕様変更内容について下記の記事で整理しています。

- [Databricks の Lakehouse federation にて BigQuery をソースにしている場合に Databricks Runtime 16.1 以降のクラスターでは Spark Connector が利用される仕様に変更 #Databricks - Qiita](https://qiita.com/manabian/items/4e87c7d185840847c674)

本記事は下記シリーズの一部です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1bb4805e-9f67-49e9-8e72-36036bf4310c.png)

出所：[Databricks で BigQuery のデータを取得する方法の徹底ガイド - Qiita](https://qiita.com/manabian/items/7097a9c31de23752d58a)

## 事前準備

### BigQuery にオブジェクトを作成

```sql
-- データセットを作成
CREATE SCHEMA IF NOT EXISTS `auth_test_03`;

-- テーブルを作成
CREATE OR REPLACE TABLE `auth_test_03.table_01` AS
SELECT *
FROM UNNEST([
  STRUCT(1 AS id, 'Alice' AS name, 100 AS score),
  STRUCT(2 AS id, 'Bob'   AS name,  95 AS score),
  STRUCT(3 AS id, 'Carol' AS name,  98 AS score)
]);


SELECT * FROM `auth_test_03.table_01`;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/2904599c-e1cb-4f37-8f2c-cc7b51eca5f4.png)

### サービスアカウント作成後にキーを取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6314a942-f11b-4ccd-a883-f6d625001ea8.png)

### BigQuery を Databricks の外部カタログに登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f41337c1-b183-49b3-9849-45f2545322a1.png)

### Databricks にてノートブック作成後に実行するコードを記述

```python
json_str = """{json_key}"""
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/dc3f9372-bbfe-444e-87fb-e6bd315e4cc1.png)


```python
# Google Cloud の プロジェクト ID をセット
project_id = "axial-triode-XXXXX"

# サービスアカウントのメールアドレスをセット
service_account_mail = "auth-test-03@axial-triode-XXXXX.iam.gserviceaccount.com"

# 取得した driver の値をセット
driver = "bigquery.shaded.com.simba.googlebigquery.jdbc42.Driver"
```

```python
# データ取得元のテーブル名を設定
table_name = "auth_test_03.table_01"

jdbc_url = (
    "jdbc:bigquery://https://www.googleapis.com/bigquery/v2;"
    f"ProjectId={project_id};"
    "OAuthType=0;"
    f"OAuthServiceAcctEmail={service_account_mail};"
    f"OAuthPvtKey={json_str};"
    "LogLevel=0;"
    "Timeout=600;"
)

bq_df = (
    spark.read.format("jdbc")
    .option("url", jdbc_url)
    .option("driver", driver)
    .option("dbtable", table_name)
    .load()
)

bq_df.limit(10).display()
```

## 4万レコード未満のテーブルにおける権限検証

### `BigQuery Data Viewer`権限の追加

権限不足によるエラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/12c56238-3a66-4772-bd28-ab0aea7ec35d.png)

> Py4JJavaError: An error occurred while calling o763.load.
: java.sql.SQLException: [Simba][BigQueryJDBCDriver](100004) HttpTransport IO error : 403 Forbidden
POST https://bigquery.googleapis.com/bigquery/v2/projects/axial-triode-XXXXX/jobs
{
  "code": 403,
  "errors": [
    {
      "domain": "global",
      "message": "Access Denied: Project axial-triode-368703: User does not have bigquery.jobs.create permission in project axial-triode-XXXX.",
      "reason": "accessDenied"
    }
  ],
  "message": "Access Denied: Project axial-triode-368703: User does not have bigquery.jobs.create permission in project axial-triode-368703.",
  "status": "PERMISSION_DENIED"
}.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0d873be4-dd8a-4909-a760-9325d29257bc.png)

### `BigQuery Job User`権限の追加

データを取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/207299cb-fe3f-4eb7-8da5-495af599d9ee.png)

## 4万レコード以上のテーブルにおける権限検証

### 4 万レコードのデータを取得

権限不足によるエラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/54e1c8c6-be74-432b-b5ae-d10e80c3dc56.png)

> Py4JJavaError: An error occurred while calling o900.load.
: java.sql.SQLException: [Simba][BigQueryJDBCDriver](100004) HttpTransport IO error : 403 Forbidden
POST https://bigquery.googleapis.com/bigquery/v2/projects/axial-triode-368703/jobs
{
  "code": 403,
  "errors": [
    {
      "domain": "global",
      "message": "Access Denied: Project axial-triode-368703: User does not have bigquery.jobs.create permission in project axial-triode-368703.",
      "reason": "accessDenied"
    }
  ],
  "message": "Access Denied: Project axial-triode-368703: User does not have bigquery.jobs.create permission in project axial-triode-368703.",
  "status": "PERMISSION_DENIED"
}.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5af17783-e09c-472b-89c7-b18ef597a52a.png)


## Databricks Lakehouse Fedearation の検証

### Databricks Runtime 16.4 での実行可否確認

権限不足によるエラーが発生します。

> Py4JJavaError: An error occurred while calling t.addCustomDisplayData.
: bigquery.storageapi.shaded.com.google.cloud.spark.bigquery.repackaged.com.google.api.gax.rpc.PermissionDeniedException: bigquery.storageapi.shaded.com.google.cloud.spark.bigquery.repackaged.io.grpc.StatusRuntimeException: PERMISSION_DENIED: request failed: the user does not have 'bigquery.readsessions.create' permission for 'projects/axial-triode-XXXX'

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/38e3afa4-4ef1-4f55-b8ac-a3f2f8135547.png)


### Databricks Runtime 15.4 での実行可否確認

データを取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/7932b54a-3759-48ee-bb8d-79451d42ea61.png)