
Omni のアクセスフィルターを使って行レベルのセキュリティを設定してみた
こんにちは、ikumiです。
複数のブランドが同一プラットフォームを使っている場合、「ブランド A の担当者にはブランド A のデータだけ見せたい」という要件が出てきます。ダッシュボードのフィルターをユーザーが外せない形で強制したい、というケースです。
Omni の アクセスフィルター(Access Filters) を使うと、ユーザーが実行するすべてのクエリの WHERE 句に自動でフィルターを適用し、自分のデータだけを見られる状態をモデルレベルで保証できます。今回はトピックへのアクセスフィルター設定から動作確認まで試してみました。
機能概要
アクセスフィルターは、ユーザー属性の値を SQL の WHERE 句に自動注入する仕組みです。ユーザーが何をしても(フィルターを外そうとしても)、SQL レベルで常にフィルターがかかるため、ダッシュボードのフィルターを隠す方法などと比べてセキュリティ上の信頼性が高い方法です。
設定するパラメーターは3つです。
| パラメーター | 必須 | 内容 |
|---|---|---|
field |
✅ | フィルター条件として使うフィールド(例: brand_ana__tran.brand) |
user_attribute |
✅ | フィールドの値と照合するユーザー属性の reference 名(例: brand) |
values_for_unfiltered |
ー | この値を持つユーザーはフィルターをスキップできる(例: [is_admin]) |
設定場所は2つあります。
| 設定場所 | パラメーター | 適用範囲 |
|---|---|---|
| トピックファイル | access_filters |
そのトピックのみ |
| モデルファイル | default_topic_access_filters |
全トピックにデフォルト適用 |
事前準備
アクセスフィルターはユーザー属性と組み合わせて動作します。まずユーザー属性を設定します。
ユーザー属性(User Attributes)を作成する
Settings → Attributes に移動し、New Attribute をクリックして以下の内容でカスタム属性を作成します。
| 項目 | 設定値 |
|---|---|
| Name | brand_kbn |
| Reference | brand_kbn |
| Type | string |
| Multiple values | No |
| Default value | (空白のまま) |
注意点としては、Default value は設定しないことを推奨します。値が未設定のユーザーに意図せずデータが表示されるのを防ぐためです。

ユーザーに属性値を割り当てる
作成した Brand 属性を選択し、Users タブを開きます。アクセスフィルターを適用したいユーザーに値(ブランド名)を入力して保存します。

今回は自分のユーザーに Celine を設定します。

また、フィルターをスキップさせたい管理者ユーザーには、is_adminを設定します。

試してみた
1. トピックにアクセスフィルターを設定する
今回適用させたい個別のTopic に access_filters を追加します。
access_filters:
- field: brand_ana__tran.brand
user_attribute: brand_kbn
values_for_unfiltered: [ is_admin ]
field: フィルターの基準にするフィールド。brand_ana__tranビューのbrandディメンションを指定しますuser_attribute: 照合するユーザー属性の reference 名。事前準備で作成したbrand_kbnを指定しますvalues_for_unfiltered:brand_kbnユーザー属性がis_adminのユーザーはフィルターをスキップできます
2. フィルターが SQL に適用されることを確認する
変更を保存し、Celine の属性値を持つユーザーで 先ほどのトピックを開きます。brand と sales_sum を選択してクエリを実行します。

SQL タブを開くと、WHERE 句に brand = 'Celine' が自動で付加されていることが確認できます。ユーザーがフィルターを操作しても、この WHERE 句は外せません。

3. 管理者ユーザーはフィルターをスキップできることを確認する
is_admin ユーザー属性を true に設定したユーザーで同じクエリを実行します。SQL の WHERE 句にブランドフィルターが含まれていなければ問題ありません。すべてのブランドのデータを確認できる状態になります。


4. モデルレベルで全トピックに一括適用する
トピックが複数あり、すべてに同じアクセスフィルターをかけたい場合は、モデルファイルに default_topic_access_filters を設定します。
モデルファイル(model.yaml など)に以下を追加します。
default_topic_access_filters:
- field: brand_ana__tran.brand
user_attribute: brand
values_for_unfiltered: [ is_admin ]
これにより、このフィールドを持つすべてのトピックに対してアクセスフィルターがデフォルトで適用されます。トピックごとに個別設定する手間が省けます。
ただし、default_topic_access_filters で指定したフィールドを持たないトピックが存在すると、そのトピックで以下のエラーが発生します。
No such access filter field "brand_ana__tran.brand" specified in default_topic_access_filters
そのため default_topic_access_filters は、モデル内のすべてのトピックが対象フィールドを持っている場合にのみ安全に使えます。フィールドを持たないトピックが混在する場合は、トピックごとに個別に access_filters を設定する方法を選んでください。
最後に
Omni のアクセスフィルターを使って、ブランドごとに見えるデータを SQL レベルで制限してみました。
ユーザーがフィルターを外せない形でデータを制限できるため、外部向けアプリケーションや、複数の取引先が同一プラットフォームにアクセスするような場面で特に有効です。values_for_unfiltered を使えば管理者や開発者はフィルターをスキップしてすべてのデータを確認できるため、開発・運用上の利便性も確保できます。
アクセスフィルターが行レベルのセキュリティを担うのに対し、列・トピックレベルのセキュリティはアクセス権(Access Grants)で制御できます。こちらについては別記事にまとめます。




