dbt Semantic Layer のサービストークンとクレデンシャルを分離したアクセス制御を試してみた

dbt Semantic Layer のサービストークンとクレデンシャルを分離したアクセス制御を試してみた

2026.04.14

はじめに

dbt Semantic Layer のサービストークンによる接続権限の分離と、モデルの出力先スキーマ分離を組み合わせた場合の動作を確認した際の内容を記事としました。

dbt Semantic Layer のクレデンシャル・サービストークンの概要

dbt Semantic Layer は dbt が提供するセマンティックレイヤーの実装を指します。

dbt Semantic Layer を経由する場合、BI などからは直接 DWH に接続せず、対象となる dbt プロジェクト専用のエンドポイントにアクセスします。BI からメトリクスなどを指定すると、内部エンジンの MetricFlow が SQL を組み立て、DWH 側にクエリを発行し結果を取得します。

この仕組みでは、2種類の認証情報を使用します。

  • サービストークン:BI などから dbt プロジェクトのエンドポイントに認証するために使用
  • DWH クレデンシャル:dbt platform から DWH への認証に使用(MetricFlow が DWH にクエリを発行する際に使用)

本機能については以下に記載があります。

https://docs.getdbt.com/docs/use-dbt-semantic-layer/setup-sl?version=1.12#add-a-credential-and-create-service-tokens

Enterprise 以上のプランでは、1つの Semantic Layer に複数の DWH クレデンシャルを登録できます。クレデンシャルとトークンを分離することで、ツール・ユーザーグループごとにアクセス制御を細かく管理できます。例えば以下のような構成が可能です。

  • 役員向け:特定スキーマのみ参照可のクレデンシャル
  • 社内分析チーム:全スキーマ参照可のクレデンシャル
  • 自動レポートサービス:専用ウェアハウスで実行するクレデンシャル

トークンを分離することで、漏洩・失効時の影響範囲を最小化できます。あるトークンが失効しても、他のツールへの影響はありません。

なお、Starter プランでは同時に作成できる認証情報は1つまでです。ただし、トークンを複数作成してこの認証情報にリンクすることはできます。

前提条件

検証環境

以下の環境を使用しています。

  • DWH:Snowflake
  • BI ツール
    • Tableau Desktop:2026.1
    • Power BI Desktop:2.152.1279.0
  • dbt platform
    • Enterprise プラン
    • セマンティックレイヤーの記法は dbt Fusion エンジンおよび dbt platform Latest リリーストラックで利用可能な新しい YAML 記法を使用しています

https://docs.getdbt.com/docs/build/latest-metrics-spec?version=1.12

事前準備

今回は以下の2つのモデルを異なるスキーマに出力し、それぞれの参照権限を持つロールで接続してトークン分離できているかを確認します。スキーマとロール構成は以下の通りです。

スキーマ ロール
PRD_ORDERS_SCHEMA PRD_ORDERS_READER ロール
PRD_CUSTOMERS_SCHEMA PRD_CUSTOMERS_READER ロール

また、各ロールにはタイムスパインテーブルの出力先スキーマ(PRD_METRICFLOW)への参照権限も付与しています。

stg_ordersorders_schema に、stg_customerscustomers_schema にそれぞれ出力するよう config を設定しています。

models/stg_orders.sql
{{ config(schema='orders_schema') }}

select
    id as order_id,
    user_id as customer_id,
    order_date,
    status

from {{ source('jaffle_shop', 'orders') }}
models/stg_orders.yml
version: 2

models:
  - name: stg_orders
    semantic_model:
      enabled: true
    agg_time_dimension: order_date

    columns:
      - name: order_id
        entity:
          type: primary
          name: orders

      - name: customer_id
        entity:
          type: foreign
          name: customer

      - name: order_date
        granularity: day
        dimension:
          type: time

      - name: status
        dimension:
          type: categorical

    metrics:
      - name: order_count
        type: simple
        agg: count
        expr: 1
models/stg_customers.sql
{{ config(schema='customers_schema') }}

select
    id as customer_id,
    first_name

from {{ source('jaffle_shop', 'customers') }}
models/stg_customers.yml
version: 2

models:
  - name: stg_customers
    semantic_model:
      enabled: true

    columns:
      - name: customer_id
        entity:
          type: primary
          name: customer

      - name: first_name
        dimension:
          type: categorical

stg_customers にメトリクスを定義していないのは、MetricFlow がメトリクスを持つセマンティックモデルに agg_time_dimension を必須とするためです。日付カラムを持たない stg_customers では定義できないため、エンティティ(customer)とディメンション(first_name)のみを提供し、stg_orders との JOIN で使う構成としています。

下図のようにモデルが作成されています。

image

クレデンシャルの追加

Snowflake 側の作業

各スキーマにアクセスするためのユーザーとロール、権限を作成します。なお、ここでは簡単に TYPE = PERSON としている点にご注意ください。

/*=============================
  PRD_CUSTOMERS_SCHEMA 参照ロール作成
=============================*/

USE ROLE SECURITYADMIN;

CREATE ROLE IF NOT EXISTS PRD_CUSTOMERS_READER
  COMMENT = 'DBT_SL_DB.PRD_CUSTOMERS_SCHEMA スキーマの読み取り専用ロール';

GRANT USAGE ON DATABASE DBT_SL_DB TO ROLE PRD_CUSTOMERS_READER;
GRANT USAGE ON SCHEMA DBT_SL_DB.PRD_CUSTOMERS_SCHEMA TO ROLE PRD_CUSTOMERS_READER;
GRANT SELECT ON ALL TABLES IN SCHEMA DBT_SL_DB.PRD_CUSTOMERS_SCHEMA TO ROLE PRD_CUSTOMERS_READER;
GRANT SELECT ON ALL VIEWS IN SCHEMA DBT_SL_DB.PRD_CUSTOMERS_SCHEMA TO ROLE PRD_CUSTOMERS_READER;
GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE PRD_CUSTOMERS_READER;

GRANT USAGE ON SCHEMA DBT_SL_DB.PRD_METRICFLOW TO ROLE PRD_CUSTOMERS_READER;
GRANT SELECT ON ALL TABLES IN SCHEMA DBT_SL_DB.PRD_METRICFLOW TO ROLE PRD_CUSTOMERS_READER;
GRANT SELECT ON ALL VIEWS IN SCHEMA DBT_SL_DB.PRD_METRICFLOW TO ROLE PRD_CUSTOMERS_READER;

GRANT ROLE PRD_CUSTOMERS_READER TO ROLE SYSADMIN;

/*-----------------------------
  PRD_CUSTOMERS_SCHEMA 参照用ユーザー作成
-----------------------------*/

USE ROLE USERADMIN;

CREATE OR REPLACE USER PRD_CUSTOMERS_READER_USER
  PASSWORD           = '<パスワード>'
  TYPE               = PERSON
  DEFAULT_ROLE       = PRD_CUSTOMERS_READER
  DEFAULT_WAREHOUSE  = COMPUTE_WH
  DEFAULT_NAMESPACE  = DBT_SL_DB.PRD_CUSTOMERS_SCHEMA
  COMMENT            = 'DBT_SL_DB.PRD_CUSTOMERS_SCHEMA 参照用ユーザー';

USE ROLE SECURITYADMIN;

GRANT ROLE PRD_CUSTOMERS_READER TO USER PRD_CUSTOMERS_READER_USER;

/*=============================
  PRD_ORDERS_SCHEMA 参照ロール作成
=============================*/

USE ROLE SECURITYADMIN;

CREATE ROLE IF NOT EXISTS PRD_ORDERS_READER
  COMMENT = 'DBT_SL_DB.PRD_ORDERS_SCHEMA スキーマの読み取り専用ロール';

GRANT USAGE ON DATABASE DBT_SL_DB TO ROLE PRD_ORDERS_READER;
GRANT USAGE ON SCHEMA DBT_SL_DB.PRD_ORDERS_SCHEMA TO ROLE PRD_ORDERS_READER;
GRANT SELECT ON ALL TABLES IN SCHEMA DBT_SL_DB.PRD_ORDERS_SCHEMA TO ROLE PRD_ORDERS_READER;
GRANT SELECT ON ALL VIEWS IN SCHEMA DBT_SL_DB.PRD_ORDERS_SCHEMA TO ROLE PRD_ORDERS_READER;
GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE PRD_ORDERS_READER;

GRANT USAGE ON SCHEMA DBT_SL_DB.PRD_METRICFLOW TO ROLE PRD_ORDERS_READER;
GRANT SELECT ON ALL TABLES IN SCHEMA DBT_SL_DB.PRD_METRICFLOW TO ROLE PRD_ORDERS_READER;
GRANT SELECT ON ALL VIEWS IN SCHEMA DBT_SL_DB.PRD_METRICFLOW TO ROLE PRD_ORDERS_READER;

GRANT ROLE PRD_ORDERS_READER TO ROLE SYSADMIN;

/*-----------------------------
  PRD_ORDERS_SCHEMA 参照用ユーザー作成
-----------------------------*/

USE ROLE USERADMIN;

CREATE OR REPLACE USER PRD_ORDERS_READER_USER
  PASSWORD           = '<パスワード>'
  TYPE               = PERSON
  DEFAULT_ROLE       = PRD_ORDERS_READER
  DEFAULT_WAREHOUSE  = COMPUTE_WH
  DEFAULT_NAMESPACE  = DBT_SL_DB.PRD_ORDERS_SCHEMA
  COMMENT            = 'DBT_SL_DB.PRD_ORDERS_SCHEMA 参照用ユーザー';

USE ROLE SECURITYADMIN;

GRANT ROLE PRD_ORDERS_READER TO USER PRD_ORDERS_READER_USER;

dbt platform 側の作業

「Project details → Semantic Layer → Edit Semantic Layer Configuration」の「Credentials & service tokens」から「Add new credential」でクレデンシャルを追加します。

image

「Add Credentials」で DWH への認証情報を指定します。

image

「Map new service token」で、この DWH 認証情報にトークンを割り当てます。

image

トークン追加後は一度しか表示されないため、控えておきます。

image

この操作を各クレデンシャルで行います。

image

BI ツール(Tableau Desktop)から接続して権限分離を確認

Tableau から接続時に、各トークンを指定します。

image

以下の2つの接続を並べて確認します。

  • 左:PRD_CUSTOMERS_SCHEMA への参照権限がある PRD_CUSTOMERS_READER ロールに紐づけたトークンで接続
  • 右:PRD_ORDERS_SCHEMA への参照権限がある PRD_ORDERS_READER ロールに紐づけたトークンで接続

2026-04-13_23h44_42

それぞれ各モデルで定義したディメンションやメトリクスを参照できています。
ただし、実際にアクセス権はないものの、このプロジェクトで定義した他スキーマのモデルのメトリクスなども表示されるようです。

次に権限分離の動作を確認します。

PRD_CUSTOMERS_READER ロールでの接続時に、PRD_ORDERS_SCHEMA 内のテーブルのメトリクスを追加しようとすると、下図のようなエラーとなりました。

2026-04-13_23h45_41

同様に、PRD_ORDERS_READER ロールでの接続時に PRD_CUSTOMERS_SCHEMA 内のテーブルのディメンションを追加しようとすると、スキーマへのアクセス権限がないエラーとなりました。

2026-04-13_23h46_08

参考までに、Power BI Desktop でも同様の動作を確認できました。アクセス権のないディメンションやメトリクス自体は表示されますが、実際に使用しようとするとエラーとなります。

image

さいごに

dbt Semantic Layer のサービストークンとクレデンシャルを分離することで、BI ツール・ユーザーグループごとに DWH へのアクセス権限を制御できることを確認してみました。
こちらの内容がどなたかの参考になれば幸いです。

この記事をシェアする

関連記事