クラウドDBへのテナント安全書き込み —— 接続・認証・RLS を一気通貫で理解する
特定の顧客(テナント)だけを対象に、記事データをクラウドDBへ安全に読み込ませる作業について、各手順の意味から積み上げて理解するためのノートである。
全体像 —— 実際に何をしているのか
[手元 PC]
↓ ① Cloud SQL Auth Proxy で安全なトンネルを張る
[クラウドDB(Cloud SQL)]
↓ ② Secret Manager からパスワードを取り出して接続
↓ ③ テナントを絞り込んで(RLS または WHERE句)
↓ ④ 1件ずつ確認・書き込み・ログ記録
大きく分けると、「安全に接続する(①②)」→「正しい相手にだけ書き込む(③)」→「証跡を残す(④)」の3段階になる。
クラウドDBへの安全な接続
Cloud SQL Auth Proxy —— 安全なトンネル
Cloud SQL Auth Proxy は、データベースの接続ポートをインターネットに公開する代わりに、Google の認証を通過した接続だけを通す「安全なトンネル(プロキシ)」である。データベースを直接インターネットにさらさずに済む。通常のデータベース接続はポートを開けて IP 許可リストで守るが、Auth Proxy はそもそもポートを公開しない。ローカルで起動すると、データベースはあたかも localhost に存在するかのように見える一方、裏側では暗号化・認証済みの通信を中継している。
./cloud-sql-proxy <project>:<region>:<instance> --port <ローカルポート>
ADC —— アプリが使う既定のログイン認証情報
ADC(Application Default Credentials)は、認証情報をコードにハードコード(=直接埋め込むこと)する代わりに、実行環境に応じた認証を自動で選択する仕組みである。自分のマシン上ではgcloud auth application-default loginで設定したユーザー認証情報を使う。
quota-project —— API利用枠と課金先の明示
quota-project は、GCP(Google Cloud Platform)の API を呼び出す際に、どのプロジェクトの利用枠と課金を使うかを明示する設定である。これがずれていると 403 エラー(サーバーが「権限がない」として拒否する状態)になることがある。ADC を設定したユーザーと呼び出し元のプロジェクトが一致しない場合に起きやすい。
gcloud auth application-default set-quota-project <project-id>
シークレットの扱い —— Secret Manager
Secret Manager は、パスワードや API キーなどのシークレット(=秘密情報)を暗号化して保管するクラウドの金庫である。コードや設定ファイルに平文で書いてはならない。
原則は次のとおりである。シークレットは実行時にのみ取得する(セッション中だけ変数に展開する)。取得した値を画面・ログ・ファイルに出力しない。スクリプトに直接書き込む(ハードコードする)ことも禁止である。
gcloud secrets versions access latest --secret=<secret-name> --project=<project-id>
マルチテナントと RLS
マルチテナント設計
マルチテナントとは、単一のデータベースやアプリケーションを複数の顧客(テナント)で共有する設計を指す。テナントごとに別システムを立てるより効率的だが、ある顧客のデータが別の顧客のデータと混ざらないよう分離を慎重に設計する必要がある。通常は各テーブルにテナントを識別するcustomer_id列を持たせ、あらゆる操作でこの列によるフィルタリングを徹底する。
RLS —— 行レベルセキュリティ
RLS(Row-Level Security)は、接続しているユーザーやセッション変数に応じて「どの行が見える/書き込めるか」を自動的に制御するデータベースのポリシー機能である。RLS が有効なデータベースに書き込む場合、ポリシーが自動的にテナントでフィルタするため、アプリケーション側は通常の INSERT を実行するだけでよい。
RLS が無効、または設定されていない環境では、アプリケーション側がフィルタリングの責任を負う。必ずWHERE customer_id = '<対象>'のような条件を付ける。条件なしの書き込みは、他テナントのデータを上書き・汚染する危険がある。
スキーマを把握する —— information_schema
スキーマとは、データベースのテーブル・列・型などの設計情報を指す。information_schema は、データベース自身がそのスキーマ情報を記述するために持つ特別な仮想テーブル群であり、どのテーブルにどの列があるかを SQL で問い合わせられる。
-- テーブル一覧
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public';
-- 列一覧
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = '<テーブル名>';
本文コンテンツの保存形式は環境によって異なり、HTML・JSON・リッチテキスト(ProseMirror や Tiptap といったエディタが出力する構造化データ)などがある。書き込む前に、実際の列の型と既存データの形式を必ず確認する。
安全な書き込み手順
- 自己確認:書き込む前に SELECT を実行し、対象テナント・対象テーブル・件数を表示して確認する。
- 1件テスト:まず1件だけ書き込み、結果が意図どおりか確認する。
- 本番は1件ずつ、または小バッチで進める:大量データを一度に流し込まない。
- 監査ログ:何を・いつ・何件書いたかを自分のマシンに記録する。
- 読み取りを先にする:必要がなければ書き込まない。まず読み取って確認する。
書き込む前に必ずこの順序で進める。確認を省いた一括書き込みが事故の原因になる。
本番ロックダウン —— 守るべき運用規律
- 事前承認なしに本番データベースを直接変更しない。
- 破壊的操作(DELETE・TRUNCATE・DROP)は、内容と影響範囲を事前に明示したうえで承認を得る。
git push --force(=履歴を上書きする強制プッシュ)は原則として禁止する。- パスワードや接続情報を含むコマンドを画面出力やログに残さない。
なぜこの規律が必要か
マルチテナント環境では、1つのミスが複数の顧客に同時に波及する。本番データベースのデータは削除すると元に戻らない(バックアップからの復元には時間とコストがかかる)。接続・認証・フィルタリングを丁寧に積み上げるのは過剰な慎重さではなく、共有環境における最低限の責任である。手順が多いのは、それだけ守るべき人とデータが多いからである。
出典・参考
元のノートに外部の出典リンクは記載されていない。
関連ノート
- Agentic Commerce — ACP and Visibility into Being 'Bought by AI'
- browser-to-api — a Browserbase skill that turns a site into OpenAPI from a CDP trace
- Cloudflare Wrangler and Pages Functions — the deployment tool and the Functions bundle
- Introduction to the Digital Architect (00) — the reality of the profession and the big picture of an original textbook series
- The textbook for becoming a digital architect — table of contents (learning roadmap)
- Why a personal site runs completely free — Cloudflare Pages + GitHub Actions