SupabaseのAPIキーとDB接続を経路から整理する

Supabaseの接続で迷ったら、最初にアプリからData APIを呼ぶのか、PostgreSQLへ直接つなぐのかを分けます。
API keyとデータベースパスワードは、どちらも接続設定に登場します。
しかし、用途、権限、保管場所は別です。
用語を接続経路へ対応させる
| 用語 | 役割 | 置く場所の原則 |
|---|---|---|
| Publishable key | クライアントからData APIへ送る公開前提のkey | Webやモバイルの公開コード |
| Secret key | RLSを迂回し得る高権限のkey | 管理下のサーバーだけ |
| Data API | HTTP経由でデータへアクセスする経路 | アプリケーションのAPI呼び出し |
| Direct connection | PostgreSQLプロトコルで直接接続する経路 | DB clientや長時間接続 |
| Session Pooler | Supavisor経由でsession単位に接続を再利用する経路 | IPv4や永続的な接続 |
| Transaction Pooler | transaction単位で接続を再利用する経路 | serverlessや短い処理 |
API keyを取得しても、psqlがDBへログインできるとは限りません。
DBパスワードを知っていても、ブラウザへ埋め込んでよいとは限りません。
先に利用目的を決める
| 目的 | 主な経路 | 認証と権限 |
|---|---|---|
| ブラウザやモバイルから読み書きする | Data APIとSupabase client | Publishable key、ユーザー認証、RLS |
| サーバーで管理処理を行う | Data APIまたはDB接続 | Secret keyまたはサーバー用DB資格情報 |
psql、DBeaver、Metabaseから接続する |
PostgreSQL接続文字列 | DB user、password、host、port |
| serverlessから短いqueryを実行する | Transaction PoolerまたはData API | clientの接続制約を確認 |
この表の経路を決めてから、必要なcredentialを発行します。
「API keyがあるからDB GUIへ接続する」という順番にしません。
Publishable keyは公開前提だが無制限ではない
SupabaseのPublishable keyは、利用者が値を取得できるWebページやモバイルアプリで使える設計です。
公開前提という意味は、keyだけで全行を読めるという意味ではありません。
Data APIでは、リクエストへ適用されるPostgres roleとRow Level Security(RLS)が実際の境界になります。
未ログインの要求は通常anonとして評価され、Supabase Authでログインした要求はauthenticatedとして評価されます。
Browser
└─ Publishable key + user JWT
└─ Data API
└─ RLS policyで行単位のアクセスを制御
Publishable keyを隠すためだけに、すべての要求を自分のserverへ中継する必要はありません。
公開経路へ出すテーブル、view、RLS policyを先に設計します。
Secret keyはバックエンド専用にする
SupabaseのSecret keyは高い権限を持ち、RLSを迂回してデータへアクセスし得ます。
管理下のserver、Edge Functions、admin backend、batch、data pipelineに限定します。
次の場所へ置きません。
- ブラウザへ返すJavaScript
- モバイルやdesktop appへ埋め込む
- Git repository、README、Issue、chat
- URLのquery parameter
- ログへ残る可能性がある入力欄
Secret keyを使うserverが、そのまま安全なadmin画面になるわけではありません。
admin authentication、操作ごとのauthorization、入力検証、audit logを別に設計します。
旧形式のkeyは移行対象として扱う
Supabaseには、従来のanonとservice_roleも残っています。
公式のAPI key資料では、新しいPublishable keyとSecret keyに対応する旧形式として説明されています。
新しいkeyを作っただけで、旧keyが自動的に無効になるとは限りません。
移行時は、環境変数、CI、Edge Functions、local設定がどのkeyを参照するかを一覧にします。
置き換えを確認した後で、旧keyを明示的に無効化する計画を作ります。
旧形式と新形式では、JWT、Authorization: Bearer、Edge Functionsの検証方法に差があり得ます。
clientや構成を変えるときは、利用中のkey形式に対応する公式資料を確認します。
Data APIとPostgreSQL接続を混ぜない
Data APIはHTTP経由でtableやviewへアクセスします。
Supabase client libraryは、認証とHTTP requestの組み立てを扱いやすくします。
DBeaverやpgcliはPostgreSQL protocolで接続します。
必要なのは、Connect画面に表示されたhost、port、database、user、passwordです。
host: db.<project-ref>.supabase.co または <region>.pooler.supabase.com
port: 5432 または 6543
database: postgres
user: Connect画面に表示された値
password: データベースのパスワード
Direct connectionとPoolerではhostやuserの形式が異なります。
例から接続文字列を推測せず、プロジェクトのConnect画面から値を取得します。
SSLの設定も公式の接続手順に合わせます。
接続文字列、DB password、secretはrepository、shell history、logへ残しません。
DirectとPoolerを接続寿命で選ぶ
| 方式 | 特徴 | 主な用途 |
|---|---|---|
| Direct connection | PostgreSQLへ直接接続。通常はIPv6 | pg_dump、migration、DB GUI、長時間動くserver |
| Shared Pooler Session | Supavisor経由。通常はport 5432 | IPv4のみの永続backend、GUIの代替 |
| Shared Pooler Transaction | Supavisor経由。通常はport 6543 | serverless、Edge Functions、短いquery |
| Dedicated Pooler | 専用resourceのPooler | 高い性能や分離が必要な用途 |
Transaction modeでは、transactionをまたいでconnectionを保持しません。
prepared statementも扱えないため、client設定で無効化が必要になる場合があります。
port 5432だからDirectとは限りません。
host名とConnect画面の説明を組み合わせて判断します。
read-onlyはkey名ではなく権限で作る
「read-only key」という名前だけで読み取り専用になると考えません。
Data APIでは、Publishable key、公開するtableやview、RLS policyで読み取り可能な範囲を作ります。
PostgreSQL clientでは、専用roleへ必要なschemaとtableのSELECTだけを付与します。
GUIのread-only settingは追加の安全策であり、DB側の権限を代替しません。
Secret keyを使ってからGUIの編集ボタンを隠す設計は、credentialが強すぎます。
事故時の影響を小さくするには、RLSまたはDB roleを先に絞ります。
用途別の選び方
Browser app
Publishable keyをクライアントへ渡し、user authenticationとRLSで制御します。
秘密keyが必要な管理処理はserver-side APIへ分離します。
Admin backendとbatch
server側でSecret keyを使うか、目的に合わせた専用DB roleを使います。
Secret keyを使う場合でも、操作を限定するauthorizationを実装します。
psqlとDB GUI
まずDirect connectionを試します。
IPv6へ接続できない場合はSession Poolerを検討します。
長時間の対話操作ではTransaction Poolerを第一候補にしません。
閲覧専用の分析tool
read-only DB roleを作り、必要なschemaとtableへだけSELECTを付与します。
PostgreSQLで接続するtoolでは、この方法がData APIより境界を説明しやすいです。
まとめ
Supabaseの用語を1つの「接続方法」として覚えません。
ブラウザとモバイルはData API、keyはPublishable key、行の境界はRLSで作ります。
サーバーの高権限処理はSecret keyまたは専用DB roleで行い、admin認証を別に設計します。
DB GUIとpgcliはPostgreSQL接続文字列を使います。
Direct、Session Pooler、Transaction Poolerは、clientの寿命とnetwork条件で選びます。
read-onlyはkey名ではなく、RLSまたはPostgreSQL権限で作ります。
