Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Multi-Tenant Data Isolation with Supabase RLS, Tested Through Real Logins in a Small Invoice Portal

2026年10月23日に「Dev.to」が公開したITニュース「Multi-Tenant Data Isolation with Supabase RLS, Tested Through Real Logins in a Small Invoice Portal」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

SupabaseのRLS機能で、1つのデータベースに複数企業のデータを安全に分離・管理する方法を解説。各企業が自身のデータのみ閲覧・操作できるよう、SQLでポリシーを設定し、実際にログインして動作検証する。複雑なフィルタリングはデータベースに任せる。

ITニュース解説

このニュース記事では、複数の顧客企業が同じデータベースを共有する「マルチテナント」環境において、それぞれの企業が自身のデータだけを見たり操作したりできるようにする重要な仕組み、「Supabaseの行レベルセキュリティ(RLS)」について、具体的な手順と検証結果を交えて解説している。システムエンジニアを目指す上で、このようなデータベースのセキュリティ対策は非常に重要な基礎知識となる。

まず、なぜこのような仕組みが必要なのかを考えよう。例えば、複数の会社が利用するオンライン請求書システムを構築する場合を想像してほしい。Acme社とGlobex社の2社が同じシステムを使っているとき、Acme社のユーザーはAcme社の請求書だけを見られ、Globex社のユーザーはGlobex社の請求書だけを見られるようにする必要がある。もし誤って他社の請求書が見えてしまったら、それは会社の信用問題や情報漏洩につながる大問題だ。

Supabase RLSは、まさにこの課題を解決するための機能だ。これは、アプリケーションのコードで「このユーザーはAcme社のユーザーだから、Acme社のデータだけを表示しよう」とフィルタリングするのではなく、データベースそのものが「このユーザーがAcme社のユーザーなら、Acme社のデータ以外は返さない」と制御する仕組みである。これにより、アプリケーション側の実装ミスによる情報漏洩を防ぎ、より堅牢なセキュリティを実現できる。

今回の記事では、具体的に以下の3つのテーブルを使ってRLSの実装と検証を行っている。

  1. tenants テーブル:顧客企業(Acme社やGlobex社)の情報を管理する。
  2. memberships テーブル:どのユーザーがどの会社に所属しているかを管理する。
  3. invoices テーブル:各会社の請求書を管理する。

これらのテーブルを作成した後、RLSを有効にする前の状態が確認された。その結果、ログインしていないユーザーでも、すべての会社の請求書データが見えてしまうことがわかった。これはまさに情報漏洩のリスクがある危険な状態だ。

次に、RLSを有効にし、具体的なセキュリティポリシーを設定する。ポリシーとは「誰が、どのような条件で、どのデータに対して、何ができるか」を定義するものだ。この記事では、主に以下の4つのポリシーが設定されている。

  • ユーザーは自身が所属する会社のメンバーシップ情報のみ見ることができる。
  • ユーザーは自身が所属する会社(テナント)の情報のみ見ることができる。
  • ユーザーは自身が所属する会社の請求書のみ見ることができる。
  • ユーザーは自身が所属する会社に対してのみ請求書を追加できる。

これらのポリシーでは、auth.uid()という関数が重要な役割を果たす。これはSupabaseが提供する機能で、現在ログインしているユーザーのIDをデータベース内で取得できる。このIDを使って、そのユーザーがmembershipsテーブルに存在するかどうか、どの会社に所属しているかを判別し、表示・操作できるデータを制限するわけだ。

ポリシーを設定した後、匿名ユーザー、Acme社のユーザー(Alice)、Globex社のユーザー(Bob)の3つの立場で、実際にデータが見えるかどうか、SQLコマンドを使って検証された。結果は以下の通りだ。

  • 匿名ユーザーは何も見えない。
  • AliceはAcme社の請求書のみが見える。
  • BobはGlobex社の請求書のみが見える。

これはRLSが期待通りに機能していることを示している。

さらに、データの「書き込み」(新しい請求書の追加)についても検証された。AliceがGlobex社の請求書を追加しようとした場合、RLSポリシーによってその操作は拒否され、エラーが発生した。これもセキュリティが正しく機能している証拠だ。

ここで一つ重要な落とし穴が指摘されている。もしAliceが「Globex社の名前を持つテナントIDを取得して、そのIDで請求書を挿入する」というSQLを書いた場合、RLSはAliceにGlobex社のテナント情報を見せないため、テナントIDは取得できず、結果として請求書は挿入されない。しかし、この場合エラーが発生せず、何も挿入されなかったという「サイレントな失敗」となるため、一見成功したように見えてしまう。RLSの書き込みポリシーをテストする際は、意図的に禁止された値を直接指定し、エラーが発生することを確認するのが確実な方法だと説明されている。

また、RLSがデータベースレベルでセキュリティを担保する一方で、アプリケーション(ウェブページ)側での表示の工夫も必要である。例えば、あるユーザーが複数の会社に所属している場合、RLSはそのユーザーに両方の会社のデータを見せる。しかし、もしウェブページが「最初の所属会社名」だけを表示し、請求書リストはすべての所属会社のものを混ぜて表示してしまうと、ユーザーは混乱するだろう。このような場合、ウェブページ側で「現在選択している会社」に基づいて表示をフィルタリングする機能や、会社を切り替える機能が必要となる。RLSはセキュリティを提供するが、ユーザーインターフェースの使いやすさはアプリケーション側で考慮する必要があるのだ。

その他にも、注意すべき点がいくつか挙げられている。RLSによって挿入が拒否された場合でも、データベースの自動採番(請求書IDなど)の番号は消費されてしまうことがある。もし請求書番号に「抜け番」が生じるのが問題となる場合は、自動採番のIDを直接請求書番号として使わず、別の採番方法を検討する必要がある。また、Supabaseの公開鍵(publishable key)はアプリケーションで利用できるが、秘密鍵(service_role key)はサーバーサイドでのみ使用し、決してウェブページや公開リポジトリに含めてはならないというセキュリティ上の重要な警告もなされている。RLSを有効にするまではデータが公開状態になるため、実際のデータを含むプロジェクトでRLS有効化前のテストを行ってはいけないとも注意喚起されている。

この解説を通じて、Supabase RLSがいかにマルチテナント環境のデータ分離に強力なツールであるか、そしてデータベースレベルでのセキュリティ対策が現代のシステム開発において不可欠であることが理解できただろう。システムエンジニアとして、このようなセキュリティ機能を正しく理解し、適切に実装・検証する能力は、信頼性の高いシステムを構築するために非常に重要となる。

関連コンテンツ

関連IT用語

関連ITニュース