KASUGAI Canvas v6.17.0

Cloud Run 認証(cloudrun / cloudrun-gate / cloudrun-iap)

← 認証とプラグインへ戻る

5〜7. Cloud Run 認証(cloudrun)

概要

Cloud Run 上のエージェントサービス(agent/・FastAPI)に実装された認証方式です。web/ の静的配信と API が同一オリジンで同居し、認証モードは環境変数 KASUGAI_AUTH_MODE で切り替えます(/auth-methods.json が動的に返されるため、モード変更にイメージ再ビルドは不要です)。

controlモード保護範囲用途
5 cloudrun(認証のみ) /api/* とデータのみ(静的は公開) 公開アプリ+秘匿データ・設定。実装が最も軽い
6 cloudrun-gate(全ゲート) 全リクエスト(Cookie ゲート) デプロイ自体を到達不可にしたい場合
7 cloudrun-iap 全リクエスト(Cloud IAP) Google アカウント運用できる組織内限定公開

Cloudflare の 3(Pages)→ 5、4(Workers)→ 6 がほぼ対応し、7 は Cloud Run 独自の追加方式です。「認証のみ・静的公開」は Cloudflare 側の制約(Pages が静的をゲートできない)の産物ではありますが、このプロジェクトでは web/ 自体が公開コードのため、静的秘匿の付加価値が小さく、まずは 5 の運用が現実的です。

構成

Cloud Run(agent/ FastAPI コンテナ)
  ├─ /                    … web/ 静的配信
  ├─ POST /api/gemini     … 内蔵AI向け Gemini プロキシ(サーバーキー注入・認可必須)
  ├─ POST /api/auth       … ID/PASS → {ok, token, kasc}(6 では Cookie も発行)
  ├─ POST /api/kasc       … トークン必須 → GCS kasc/<projectId> へ書き込み
  ├─ GET|PUT /api/data/*  … トークン必須 → GCS data/<key>(GET は署名付き URL へ 302)
  └─ GET /api/capabilities … {tier:"cloudrun", features, auth:{mode}, ai, google?}
                               GOOGLE_MAPS_API_KEY 設定時は google.mapsApiKey を通知

Cloud Storage(KASUGAI_GCS_BUCKET)
  ├─ kasc/<プロジェクトID>  … .kasc 本文(Cloudflare の kasc:<id> 相当)
  └─ data/<キー>          … gs:// で参照される秘匿データ

.kasc 内で gs://<キー> と書いたレイヤーは /api/data/<キー>?token=… に書き換えられて配信されます(Cloudflare の r2:// に相当。r2:// も移行用に読み替えられ、保存時は gs:// に正規化されます)。GET は既定で GCS V4 署名付き URL へ 302 リダイレクトするため、大きなデータもコンテナを通りません(KASUGAI_DATA_REDIRECT=0 でプロキシ配信に切替可・Range 対応)。

起動時に web/projects/*/*.kasc がストレージへ冪等シードされます(KASUGAI_SEED_KASC=0 で無効化)。秘匿したい .kasc は静的配信から削除してください — モード5 では web/projects/* は公開のままです。

利用シーン

  • モード5:審査用デモ・一般公開しつつ設定とデータだけ保護したい。最も負荷が軽い推奨構成
  • モード6:改造版 web/ を秘匿したい、デプロイ自体の存在を限定したい場合
  • モード7:Google アカウントでアクセス管理できる社内・組織内向け。認証コードはほぼ不要

モード別の設定(Canvas 側 ⇄ Cloud Run 側)

Canvas(web/)側:Cloud Run が web/ を同一オリジン配信する構成では、KASUGAI_AUTH_MODE から /auth-methods.json が動的に返るため web/ 側の設定変更は不要です(モード変更も再ビルド不要)。web/ を別途静的配信する場合だけ auth-methods.json の control を手動で 5/6/7 に設定してください。

設定項目5 cloudrun6 gate7 iap
KASUGAI_AUTH_MODE567
KASUGAI_AUTH_USER/PASS必須(Secret Manager)必須(同左)不要
KASUGAI_GCS_BUCKET.kasc・データ利用時同左.kasc 編集保存する場合のみ
KASUGAI_IAP_AUDIENCE−−署名検証する場合
デプロイフラグ--allow-unauthenticated--iap
インフラ前提バケット+SA 権限(GCS 利用時)OAuth 同意画面+iap.httpsResourceAccessor

デプロイ手順

リポジトリ直下の run-cloudrun.py が、API 有効化 → Artifact Registry → Cloud Build(ローカルの Docker 不要)→ Secret Manager → GCS バケット・権限付与 → gcloud run deploy → 動作確認までを一括で行います。Cloud Shell(ブラウザターミナル)でも実行できます。

python run-cloudrun.py --gemini-api-key KEY --maps-api-key MAPS_KEY \
  --auth-mode 5 --auth-user ID --auth-pass PASS --bucket kasugai-data-xxxx

初回デプロイ後は非秘密の設定が kasugai_canvas.cloudrun.json(gitignore)に保存されるため、再デプロイは引数なしの python run-cloudrun.py(または python run.py --cloudrun)だけで実行できます。シークレットは Secret Manager の既存登録が再利用されます。agent/cloudrun.kasc が存在すると、デプロイ時に gs://<bucket>/kasc/default へアップロードされ、Cloud Run 版だけが web/projects/ とは別の初期 .kasc で動きます(ベースマップ透明+Google 3D ON+レイヤー OFF の提出用初期状態を同梱済み。起動時シードは既存オブジェクトを上書きしないため維持される。--kasc none で無効化・--kasc PROJ:FILE でプロジェクト指定可)。

手動で行う場合は agent/README.md の手順どおりです(コンテキストはリポジトリ直下)。以下は手動運用時の個別手順です。

  1. GCS バケットを用意します(モード5/6 で .kasc・データを使う場合)。
    gcloud storage buckets create gs://kasugai-data --location=asia-northeast1
  2. 実行サービスアカウントに権限を付与します(署名付き URL を使う場合)。
    # signBlob 用(自身への Token Creator)+ バケットのオブジェクト管理
    gcloud iam service-accounts add-iam-policy-binding SA_EMAIL \
      --role=roles/iam.serviceAccountTokenCreator --member=serviceAccount:SA_EMAIL
    gcloud storage buckets add-iam-policy-binding gs://kasugai-data \
      --role=roles/storage.objectAdmin --member=serviceAccount:SA_EMAIL
    gcloud services enable iamcredentials.googleapis.com
  3. 署名 URL 方式を使う場合はバケットに CORS を設定します(302 後はクロスオリジンになるため必須)。
    gcloud storage buckets update gs://kasugai-data --cors-file=cors.json
    # cors.json:
    # [{"origin":["https://<app>.a.run.app"], "method":["GET","PUT"],
    #   "responseHeader":["Content-Type","Content-Range","ETag"], "maxAgeSeconds":3600}]
    未設定でも動きますが KASUGAI_DATA_REDIRECT=0(プロキシ配信)で運用してください。
  4. ID/PASS を Secret Manager に登録します(モード5/6)。
    gcloud secrets create kasugai-auth-user --data-file=- <<< admin
    gcloud secrets create kasugai-auth-pass --data-file=- <<< '********'
  5. デプロイします。
    # モード5(認証のみ)
    gcloud run deploy kasugai-canvas \
      --image asia-northeast1-docker.pkg.dev/PROJECT/kasugai/kasugai-canvas \
      --region asia-northeast1 --allow-unauthenticated --min-instances 1 \
      --set-env-vars KASUGAI_AUTH_MODE=5,KASUGAI_GCS_BUCKET=kasugai-data \
      --set-secrets KASUGAI_AUTH_USER=kasugai-auth-user:latest,KASUGAI_AUTH_PASS=kasugai-auth-pass:latest
    
    # モード7(IAP。認証はインフラ側)
    gcloud run deploy kasugai-canvas --image ... --iap
    --min-instances 1 はフロントの /health 検出(1秒タイムアウト)がコールドスタートを逃さないための推奨設定です。
  6. 動作確認します。トップページでログイン画面(5/6)または Google ログイン(7)が出ること、誤パスワードで 401、ログイン後にレイヤーが表示されることを確認します。

環境変数

変数用途
KASUGAI_AUTH_MODE5/6/7 で起動制御を有効化(未設定は認証なし)
KASUGAI_AUTH_USER/KASUGAI_AUTH_PASSモード5/6 の ID/PASS(Secret Manager 推奨)
KASUGAI_TOKEN_SECRETトークン署名鍵(未設定時は KASUGAI_AUTH_PASS)
KASUGAI_GCS_BUCKET.kasc・秘匿データの格納バケット(未設定時はローカル .datastore/・開発用)
KASUGAI_DATA_REDIRECT0 で GET /api/data をプロキシ配信(既定 1=署名 URL へ 302)
KASUGAI_SIGNED_URL_TTL署名 URL 有効期限秒(既定 900)
KASUGAI_IAP_AUDIENCEモード7 の IAP JWT audience(設定時は署名検証)
KASUGAI_SEED_KASC0 で起動時の .kasc シードを無効化
GEMINI_API_KEYGemini API キー。/api/gemini でサーバーキー注入に使用(Secret Manager 推奨)
GOOGLE_MAPS_API_KEYMaps Platform キー。/api/capabilities 経由でブラウザへ配布(秘匿ではない。リファラ制限で保護)

資産ごとの秘匿状況

資産5 cloudrun6 cloudrun-gate7 cloudrun-iap
ID/PASS ✅ 環境変数のみ
Secret Manager 推奨
✅ 同左 ✅ Google アカウント
アプリは資格情報を持たない
.kasc 設定 ◐ GCS 内で秘匿
ログイン後は全量がブラウザへ配信
◐ 同左 ◐ IAP 内側
静的ファイルでよい場合は GCS 不要
HTML/JS/CSS
(アプリ本体)
❌ 全公開 ✅ 未ログインは 401
ログイン画面系のみ公開
✅ IAP がリダイレクト
データ(web/) ❌ 列挙容易 / △ obscurity ✅ 未ログインは 401 ✅ IAP 内側
データ(gs:// 経由) ✅ トークン必須
署名 URL は期限付きベアラ
✅ 同左(Cookie でも可) ✅ IAP JWT or トークン
/api/gemini ✅ kasugai トークン or Bearer ✅ Cookie セッション ✅ IAP JWT
Maps API キー
(GOOGLE_MAPS_API_KEY)
❌ 公開 — capabilities 経由でブラウザへ配布。タイル URL に露出する設計上の公開キーなので、GCP の HTTP リファラ制限で保護

✅ 秘匿 ◐ 条件付き ❌ 公開 ——「ログインした人」からは .kasc・データは見えます。秘匿が効くのは未ログインの第三者に対してです。署名付き URL は発行時点で認証済みの期限付きベアラ URL なので、有効期間内は誰でも使えます(r2:// の ?token= と同等のリスク)。

セキュリティ上の注意

  • トークン形式は Cloudflare 版と同じ expiry.HMAC-SHA256。秘密鍵は KASUGAI_TOKEN_SECRET(未設定時 KASUGAI_AUTH_PASS)
  • プロセス内レート制限はマルチインスタンス環境ではベストエフォートです。本格運用では外部 HTTPS LB + Cloud Armor を前段に置いてください(run.app 直の構成では Cloud Armor は使えません)
  • モード6 の Cookie は HttpOnly・Secure・SameSite=Strict・12時間。モード7 は署名検証用の KASUGAI_IAP_AUDIENCE 設定を推奨(未設定でも IAP 直下では到達自体が認証済みですが、防御の深さとして)
  • Cloud Run のリクエスト上限は 32MiB です。それを超えるデータアップロードは署名付き URL 直 PUT が必要です(現状の PUT はプロキシ経由)