EP.14 で、データ層とセマンティック層を分ける話をしました。この回は、そこにアクセス制御をどう組み込むかを扱います。
「誰に何を見せるか」は、どの層で決めるかによって管理のしやすさが大きく変わります。
1. 方式は4つ
実現方法を並べると、単純なものから柔軟なものへという順に並びます。柔軟になるほど、管理と把握が難しくなります。
| 方式 | 単純さ | 柔軟さ | 把握のしやすさ |
|---|---|---|---|
| 表そのものを分ける | 最も単純 | 低い | 最も分かりやすい |
| ビューで絞る | 単純 | 中 | 定義を読めば分かる |
| 行レベルで制御() | 中 | 高い | 分かりにくい |
| 列レベルで制御 | 中 | 高い | 分かりにくい |
最下2行が強力ですが、把握が難しい。同じ表を参照しても、人によって結果が違います。これが便利さの源であり、同時に最大の難点でもあります。
行や列の制御が入っていると、同じクエリでも人によって結果が違います。「私の画面では1000件なのに、あなたのでは800件」という状況が起きる。設定の存在を知らないと、原因にたどり着けません。データ基盤トラブル事件簿 EP.06 で扱った問題の一因になりえます。
2. どこから始めるか
最初から柔軟な方式を選ばないでください。必要になってから移行するのが原則です。
| 状況 | 適した方式 | 理由 |
|---|---|---|
| 部門が2〜3、見せる範囲が固定 | 表を分ける | 単純で確実 |
| 見せる列だけが違う | ビューで絞る | 定義が明示的 |
| 人ごとに見える行が違う | 行レベルの制御 | 表を人数分作れない |
| 同じ表で機微な列だけ隠す | 表を分けるより管理が楽 |
3行目が移行の境目です。人数分の表を作れなくなったら、制御に移ります。逆に言えば、表の数で管理できるうちは、そのほうが分かりやすい。
この判断は Snowflake 実践ハンドブック EP.08 で扱ったロール設計と同じ構造です。最初は少数から始め、実際に困ってから分ける。
3. 一箇所に集約する
最も重要な原則です。制御を複数の層に分散させない。分散すると、全体として誰が何を見られるかを、誰も説明できなくなります。
| 制御の置き場 | 起きること |
|---|---|
| データベース側だけ | 一箇所で完結。把握しやすい |
| アプリ側だけ | 把握しやすいが、直接接続で回避される |
| 両方に分散 | 足し算になり、把握できない |
| さらにBIツールにも | 説明不能 |
3行目と4行目が実際によく起きます。「念のため両方に入れておく」という判断の結果です。安全側に見えますが、どちらが効いているか分からなくなり、変更もできなくなります。
原則は、データベース側に寄せることです。直接接続されても効くのはこの層だけだからです。アプリ側の制御は、利便性のためのもの(見せない項目を出さない)と位置づけ、安全性はデータベース側で担保します。
4. 設定を可視化する
制御方式の最大の難点は、存在が見えないことでした。これは明示的に可視化するしかありません。
- 1どの表に、どの制御がかかっているかを一覧化する
- 2制御の定義をコードで管理する — 画面で設定して終わりにしない
- 3利用者に「絞られている」ことを伝える — 件数の脇に注記など
- 4制御を含めたテストを書く — 役割ごとに期待する結果を確認
- 5定期的に棚卸しする — Snowflake EP.08 と同じ
3番目が実務では効きます。利用者が「自分は絞られた結果を見ている」と知っているだけで、数字の食い違いの調査が大幅に短縮されます。
-- 行レベルの制御が設定されている表を洗い出す(PostgreSQL の例)SELECT schemaname AS スキーマ, tablename AS テーブル, policyname AS ポリシー名, roles AS 対象ロール, cmd AS 対象操作, qual AS 絞り込み条件FROM pg_policiesORDER BY schemaname, tablename;
-- 行レベルの制御が有効な表(ポリシーが無いと全て見えなくなる点に注意)SELECT n.nspname AS スキーマ, c.relname AS テーブル, c.relrowsecurity AS 制御有効, c.relforcerowsecurity AS 所有者にも適用FROM pg_class cJOIN pg_namespace n ON n.oid = c.relnamespaceWHERE c.relrowsecurityORDER BY 1, 2;この一覧を定期的に出力して、想定と一致しているか確認してください。設定は増えていきます。「いつの間にか制御が外れていた」「意図しない表に制御が入っていた」を検知できます。特に前者は見えすぎる方向の誤りなので、指摘されるまで気づけません。
5. 機微な列の扱い
個人情報などの機微な列は、列レベルの制御か で扱います。方式によって性質が違います。
| 方式 | 見え方 | 元に戻せるか | 向く場面 |
|---|---|---|---|
| 列ごと隠す | 列が存在しない | — | その役割には全く不要 |
| 一部を伏せる | 「山田 ***」 | 戻せない | 本人確認の補助には使える |
| 別の値に置き換える | 一貫した偽の値 | 設計次第 | 開発・検証環境 |
| 集計のみ許可 | 個別は見えない | — | 分析用途 |
3行目が検証環境で重要です。Snowflake EP.07 で扱ったとおり、本番の複製には本番と同じ機密性があります。置き換えたうえで配ると、開発の利便性と安全性を両立できます。
ただし一貫した置き換えであることが条件です。同じ人が常に同じ偽名になるようにしないと、結合や集計の検証ができません。ランダムに置き換えると、開発環境として使えなくなります。
6. 判断の整理
最後に、設計の順序をまとめます。
- 1まず表を分けられないか考える — 単純さは価値
- 2分けられないなら、制御を検討する — 人ごとに違うなら行、列だけなら列
- 3置き場は一箇所に決める — 分散させない(データベース側に寄せる)
- 4設定を一覧化して定期確認する — 増えるものは棚卸しが要る
- 5利用者に「絞られている」ことを伝える — 調査の短縮になる
- 6制御を含めたテストを書く — 役割ごとの期待結果
6番目を忘れないでください。制御の設定を変えたときに、意図しない範囲が見えるようになっていないかを確認する必要があります。LLM時代のテスト戦略 EP.05 で扱ったリグレッションの対象として、最も影響の大きい部類です。見えすぎる方向の誤りはエラーにならず、指摘されるまで気づけません。
方式は表を分ける → ビュー → 行/列の制御の順に柔軟になるが、把握は難しくなる。表の数で管理できるうちは分けるほうが分かりやすい。制御は一箇所に集約し(データベース側に寄せる)、設定を一覧化して定期確認する。そして利用者に絞られていることを伝えるだけで、数字の食い違いの調査が大幅に短縮されます。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。