Databricks Unity Catalog のタグ機能活用術

みなさん、こんにちは！
Unity Catalog にはタグ機能があり、カタログからテーブルの列まで任意のタグをつけることができます。
タグ機能は単なるオブジェクトの情報整理にとどまらず、検索の効率化や、Unity Catalog の内部情報を利用した分析などに活用できる便利なものです。

本記事ではそんな Unity Catalog のタグ機能と活用方法に焦点を当ててご紹介します。

## タグ
Unity Catalog ではカタログ、スキーマ、テーブルそれぞれに対してタグを付けることができます。
タグはキーと値からなり、任意のタグを複数個付けることが可能です。

以下は従業員のIDと名前、メールアドレス、給料などの情報を含むemployeesテーブルへのタグ付け例です。テーブル自体には`personal_info`と`sensitive`のタグを付け、address列とsalary列にはそれぞれ`sensitive`タグを付けています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/370bafe9-88d3-456e-93de-c9dfce56ca80.png)

## 検索
タグはオブジェクトの情報をわかりやすくなるだけではなく、検索機能と連携しているため、タグを使用することで検索の効率を高めることができます。

例えば Ctrl + P で検索ページを開き、「タイプ: テーブル」「タグ: sensitive」で検索をかけると以下のように表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/82c830d6-5245-47aa-85d7-d61bae9b5e3a.png)
※例は1つだけですが、タグは複数個指定することも可能です。

## 分析
Unity Catalog 内のデータのアクセス権限やタグに関するデータは`system.information_schema`に格納されます。このデータを利用し、特定のタグをもつオブジェクトに対して誰がどのような権限をもっているかを確認することが可能です。

まず、以下のSQLで必要なデータを含む一時ビューを作成します。
```ruby:qiita.rb
-- オブジェクトごとのタグデータの一時ビュー作成
CREATE OR REPLACE TEMPORARY VIEW object_tags AS (
  SELECT
    concat(catalog_name, '.', schema_name, '.', table_name) AS object,
    'table' AS object_type,
    sort_array(collect_set(tag_name)) AS tags
  FROM
    system.information_schema.table_tags
  GROUP BY
    1,
    2
  UNION ALL
  SELECT
    concat(catalog_name, '.', schema_name) AS object,
    'schema' AS object_type,
    sort_array(collect_set(tag_name)) AS tags
  FROM
    system.information_schema.schema_tags
  GROUP BY
    1,
    2
  UNION ALL
  SELECT
    concat(catalog_name) AS object,
    'catalog' AS object_type,
    sort_array(collect_set(tag_name)) AS tags
  FROM
    system.information_schema.catalog_tags
  GROUP BY
    1,
    2
  UNION ALL
  SELECT
    concat(catalog_name, '.', schema_name, '.', table_name) AS object,
    'table' AS object_type,
    sort_array(collect_set(tag_name)) AS tags
  FROM
    system.information_schema.column_tags
  GROUP BY
    1,
    2
)

-- オブジェクトごとの権限データの一時ビュー作成
CREATE OR REPLACE TEMPORARY VIEW privileges AS (
  SELECT
    concat(
      table_catalog,
      '.',
      table_schema,
      '.',
      table_name
    ) AS object,
    'table' AS object_type,
    grantee,
    privilege_type
  FROM
    system.information_schema.table_privileges
  UNION ALL
  SELECT
    concat(catalog_name, '.', schema_name) AS object,
    'schema' AS object_type,
    grantee,
    privilege_type
  FROM
    system.information_schema.schema_privileges
  UNION ALL
  SELECT
    catalog_name AS object,
    'catalog' AS object_type,
    grantee,
    privilege_type
  FROM
    system.information_schema.catalog_privileges
)

-- オブジェクトごとの権限とタグデータの一時ビュー作成
CREATE OR REPLACE TEMPORARY VIEW privileges_and_tags AS (
  SELECT
    t.object,
    t.object_type,
    p.grantee,
    p.privilege_type,
    t.tags
  FROM
    object_tags t
    JOIN privileges p ON t.object = p.object
    AND t.object_type = p.object_type
  WHERE
    NOT (
      startswith(p.object, '__databricks_internal.')
      OR contains(p.object, 'information_schema')
    )
    AND array_contains(t.tags, 'sensitive')
)
```
以下を実行すると、sensitiveタグを持つデータにアクセス可能なユーザ一覧を取得することができます。

```ruby:qiita.rb
SELECT * FROM privileges_and_tags ORDER BY object ASC
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/cc57c1e1-012f-4026-805d-fb37245f3ea6.png)

HRグループにはemployeesテーブルに対する`ALL PRIVILEGES`権限を与えており、テスト用サービスプリンシパル（64edb...）にはスキーマレベルで`SELECT`権限を与えていたため、その情報が正しく表示されていることが確認できます。

また、以下で権限を有しているユーザとグループのオブジェクトごとの総数を取得することができます。
```ruby:qiita.rb
SELECT 
grantee AS group, 
privilege_type,
object_type AS object_with_sensitive_tag,
count(*) AS total
FROM privileges_and_tags
GROUP BY 1, 2, 3
ORDER BY total DESC
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3956386/aa2a75a8-c2c5-441e-b27a-c0e4104fbdca.png)

## さいごに
Unity Catalog のタグ機能は通常の用途にとどまらず、Unity Catalog の内部情報と組み合わせることでテーブルなどの適切なアクセス権限管理にも繋げることができます。

タグを付けるのはちょっと面倒だし、そこまでメリットを感じない・・・と思われていた方も、本記事を通してタグ機能の有用性を少しでも感じていただけたら幸いです。

## 参考
* [Identifying and Tagging PII data with Unity Catalog](https://medium.com/databricks-platform-sme/identifying-and-tagging-pii-data-with-unity-catalog-870522f25730)