コンテンツにスキップ

Claude CodeでWebアプリに管理画面を追加してCloudflare Accessでアクセス制限する

⚠️ このハンズオンは制作途中です。動かしてみることはできますが、説明や手順が今後書き換わる可能性があります。気になる点があればフィードバックいただけると助かります。

このハンズオンはD1ハンズオンGitHub Actions版はこちら)の続編。前回作った匿名一行掲示板に、管理者だけが使える管理画面を追加する。

DBを使うWebアプリには、DB管理という問題が付きまとう。掲示板なら「不適切な投稿を削除したい」「スパムを非表示にしたい」といった操作が必要になる。そのたびに SQL を直接叩くのは手間だし、ミスのリスクもある。

こうした管理操作はWebアプリの中に管理画面として用意しておくのが定石。必要な操作をボタンひとつでできるようにしておけば、後の運用がぐっと楽になる。

ただし、管理画面は誰でもアクセスできてはまずい。一般ユーザーが投稿を操作できてしまう。特定の人(管理者)だけが入れるように制限する必要がある。

ということで、このハンズオンでは、前回作った掲示板に以下を追加する。

  • 管理画面/admin):投稿の表示/非表示を切り替えられる
  • Cloudflare Access/admin/api/admin を Google 認証でアクセス制限する

掲示板

前回作った掲示板

掲示板

今回作る管理画面

1-2. なぜ Cloudflare Access を使うのか

Section titled “1-2. なぜ Cloudflare Access を使うのか”

管理画面を手軽に守るなら、Basic認証で制限するハンズオンで扱った合言葉方式がある。ただし合言葉方式には「誰がアクセスしたかを区別できない」という限界がある。Cloudflare Access を使えば、Google アカウントによる認証を Cloudflare 側で肩代わりしてくれる。コードを書かずに「このメールアドレスだけアクセスを許可」という設定ができ、Google の2段階認証やパスキーの恩恵もそのまま受けられる。

Cloudflare Access は無料枠で 最大50ユーザー まで使える。この上限から、向き不向きが見えてくる。

向いていないこととしてあげられるのは、一般公開するWebアプリの会員登録・ログイン機能として使うこと。50人を超えた時点で有料プランが必要になるため、不特定多数のユーザーに使ってもらうサービスには向かない。

向いていることとしてあげられるのは、管理画面のアクセス制限。管理者は多くても数人なので、50ユーザーの上限はまったく問題にならない。しかもコードを書かずにダッシュボードだけで設定が完結する。このハンズオンのように「自分だけ入れる管理画面」を作る用途にはうってつけ。

このハンズオンでやることの全体像。

  1. Cloudflare Access 設定(ブラウザ操作)
    • Zero Trust ダッシュボードで /admin と /api/admin を Google 認証で保護
  2. D1 スキーマ変更(Claude Code)
    • posts テーブルに hidden カラムを追加
  3. バックエンド追加(Claude Code)
    • 非表示フラグを更新する API を追加
    • 公開側 API で hidden 投稿を除外
  4. フロントエンド追加(Claude Code)
    • /admin ページを作成
  5. デプロイして動作確認
    • push → GitHub Actions / Git連携 → Cloudflare に反映

D1 スキーマ変更〜フロントエンドの実装は Claude Code にプロンプトで依頼できる。Cloudflare Access の設定だけブラウザでの手作業が必要。

2章は手順が多いが、初回限定の作業が含まれているのが理由。Zero Trust の初回セットアップ(2-1 後半)と Google の IdP 登録(2-2・2-3)は一度やれば済む。2回目以降に別のアプリへ Access をかける場合は 2-4 だけで完結する。

前提:Claude Codeの作業フォルダは前回のハンズオン(D1ハンズオン / GitHub Actions版)で作った ~/claude/my-bbs

このハンズオンのプロンプトは、掲示板の標準構成(投稿テーブル posts/公開API /api/posts)を前提にしている。D1ハンズオンでエージェントが別の名前(messages など)で作っていた場合は、その名前に読み替える。プロンプトに「このアプリの投稿テーブルとAPIパスに合わせて」と添えれば、エージェントが既存コードを読んで合わせてくれる。

2. Cloudflare Access の設定(ブラウザ操作)

Section titled “2. Cloudflare Access の設定(ブラウザ操作)”

2回目以降の人へ:左サイドバーの Zero TrustAccess controlsApplications に進んで 2-4 から開始すればOK(2-1〜2-3は初回のみの作業)。

2-1. Zero Trust の初回セットアップ

Section titled “2-1. Zero Trust の初回セットアップ”

Cloudflare ダッシュボードを開き、左サイドバーの Zero Trust をクリック。

Zero Trust

Zero Trust

Get started をクリック。

チーム名の入力画面が出る。任意の文字列でよい(後から変更可能)。入力して Next

your team name

Choose your team name

プラン選択画面が出る。Zero Trust FreeSelect plan をクリック。

支払い情報の入力画面が出る。無料プランでもカード登録が必要。Review and purchasePurchase($0)をクリック。

「Get started with Cloudflare Zero Trust」という案内ページが出る。Skip this for now をクリックすると左サイドバーが表示される。

2-2. Google を ID プロバイダーとして登録

Section titled “2-2. Google を ID プロバイダーとして登録”

左サイドバー IntegrationsIdentity providers を開く。

Add an identity provider をクリック → プロバイダー一覧から Google を選択。

App ID(= Google のクライアント ID)と Client Secret(= Google のクライアントシークレット)の入力欄が表示される。次節で取得した値を貼る。

2-3. Google Cloud Console で OAuth クライアントを作成

Section titled “2-3. Google Cloud Console で OAuth クライアントを作成”

2章でGoogle側の操作が必要なのはここだけ。 それ以外はすべてCloudflareのダッシュボードで完結する。

Google Cloud Console を開く。

上部のプロジェクト選択ドロップダウン → 新しいプロジェクト → プロジェクト名を入力(例:cloudflare-access)→ 作成

左サイドバー APIs & Services認証情報 を開く。OAuth クライアント ID の作成を試みると、まず同意画面の設定が必要と案内される。同意画面を構成 をクリック。

Google Auth Platform の画面で 開始 をクリックし、以下を設定する。

項目
アプリ名任意(例:cloudflare-access
ユーザーサポートメール自分のメールアドレス
対象外部
連絡先情報自分のメールアドレス

最後に利用規約への同意チェックを入れて 作成

2-3-3. OAuth クライアント ID を作成する

Section titled “2-3-3. OAuth クライアント ID を作成する”

左サイドバー クライアントクライアントを作成 をクリック。

項目
アプリケーションの種類ウェブ アプリケーション
名前任意(例:cloudflare-access
承認済みのリダイレクト URIhttps://<チーム名>.cloudflareaccess.com/cdn-cgi/access/callback

リダイレクト URI の <チーム名> は 2-1 で設定したチーム名に置き換える(例:チーム名が kerokero なら https://kerokero.cloudflareaccess.com/cdn-cgi/access/callback)。

作成 をクリックするとクライアント ID とクライアントシークレットが表示される。ダイアログを閉じると二度と表示されないのでその場でコピーする。

2-3-4. Cloudflare に値を貼り付けて保存する

Section titled “2-3-4. Cloudflare に値を貼り付けて保存する”

Cloudflare の Add Google 画面に戻り、以下を入力して Save

項目
App IDGoogle のクライアント ID
Client secretGoogle のクライアントシークレット

一覧画面に戻ったら Test をクリックして Google 認証が通ることを確認する。

左サイドバー Access controlsApplicationsCreate new application をクリック。

Continue with Self-hosted and private を選択。

Destinations セクションで、Domain 入力欄の Switch to custom input をクリックし、掲示板のURL/admin(例:my-bbs-90t.pages.dev/admin)を入力する。

同じ要領で2つ目の Destination として 掲示板のURL/api/admin(管理操作API用)も追加する。

この2つを追加しておけば、/admin/api/admin 自身に加えて、/admin/foo/api/admin/posts/1 のような子パスもまとめて保護される(実際の動作確認は 6-2 で行う)。

Access policies セクションで Create new policy をクリックし、以下を設定する。

項目
Policy name任意(例:admin-only
ActionAllow
Include の SelectorEmails
Include の Value自分のメールアドレス

Save policy → 右下 Details の Name に任意のアプリ名(例:my-bbs-admin)を入力 → Create をクリック。

これで /admin 配下と /api/admin 配下(管理APIの子パスを含む)に Cloudflare Access のアクセス制限が設定された。実際の動作確認は管理画面を実装してデプロイした後(6-2)。

3. 【データベース】スキーマ変更

Section titled “3. 【データベース】スキーマ変更”

「投稿を非表示にする」機能を実装するには、投稿ごとの「表示/非表示」状態をDBに保存する必要がある。Claude Code に「投稿を非表示にできる管理画面を作りたい」と相談すると、hidden カラムの追加が提案される。ここではその手順を先に進める。

マイグレーションファイルの作成を Claude Code に依頼する。

Claude
投稿テーブル(掲示板なら posts)にhiddenカラム(INTEGER型、デフォルト0)を追加するマイグレーションファイルを作成して。テーブル名は既存のスキーマに合わせて。ファイル名はmigrations/0002_add_hidden.sqlで

作成されたファイルを確認する。内容はこのようになっているはず。

ALTER TABLE posts ADD COLUMN hidden INTEGER NOT NULL DEFAULT 0;

マイグレーションファイルは wrangler.jsoncmigrations_dir で指定したフォルダに置く。GitHub Actions 方式なら push 時に自動適用される。Git連携方式なら push 前に npx wrangler d1 migrations apply my-bbs-db --remote を手元から実行する。

4. 【バックエンド】管理画面用 API の追加

Section titled “4. 【バックエンド】管理画面用 API の追加”

管理操作のAPIは /api/admin/ 配下に置く。Cloudflare Access で /api/admin/* をまとめて保護するため、公開側API(/api/posts)と区別する。

Claude Code に依頼する。

Claude
既存の投稿API(掲示板なら /api/posts)と投稿テーブルに合わせて、以下の3点をfunctions/api/配下に追加・修正して。エンドポイント名・テーブル名は既存のものに揃えて。
1. GET /api/admin/posts を追加する。hiddenの値にかかわらず全投稿を返す
2. PATCH /api/admin/posts/:id を追加する。リクエストボディのhiddenフィールド(0か1)で投稿テーブルのhiddenカラムを更新する
3. GET /api/posts でhidden=0の投稿だけを返すようにする

公開側の /api/posts からは非表示投稿が消え、管理用の /api/admin/posts では全投稿(非表示も含む)が見える、という分担になる。

5. 【フロントエンド】管理画面の作成

Section titled “5. 【フロントエンド】管理画面の作成”

Claude Code に依頼する。

Claude
管理画面(public/admin/index.html)を作って。
GET /api/admin/posts で全投稿を一覧表示して、各投稿の表示/非表示を切り替えられるようにしたい。
一覧はテーブルで、各行にボタンをつけて。非表示中の投稿はグレーアウトして。ユーザー入力にはXSS防止の処置を入れる。シンプルなデザインで。

6-1. push して GitHub 経由で Cloudflare にデプロイ

Section titled “6-1. push して GitHub 経由で Cloudflare にデプロイ”

変更をコミット・push する。

Claude
今回の変更をコミットしてpushして

GitHub の Actions タブ、または Cloudflare ダッシュボードの Deployments で進行状況を確認する。

本番 URL の /admin にアクセスすると、Cloudflare の Google 認証画面が表示される。

sign in with google

Sign in with google

登録したメールアドレスで認証すると管理画面に入れる。別のアカウントでは弾かれることも確認しておく。

さらに、管理API の子パスが保護されていることも確認する。ブラウザのシークレットウィンドウで https://掲示板のURL/api/admin/posts/1 を直接開き、Cloudflare Access の認証画面に飛ばされる(=保護されている)ことを確認する。

以前に Cloudflare Access で認証済みの場合、セッションが残っていて認証画面なしでアクセスできることがある。認証画面を確認したいときは、Chromeのシークレットウィンドウで開く。

  • Cloudflare Access の設定は wrangler.jsonc や GitHub Actions のワークフローとは独立している。Cloudflare ダッシュボード側の設定のみで完結する
  • Session duration を短くするとセキュリティは上がるが、作業中に認証が切れて不便になる。個人用途なら 24 hours で十分
  • Google Cloud Console の OAuth クライアントは無料で作成できる。課金設定は不要
  • Google Cloud Console の OAuth クライアント作成はアプリ全体で一度だけ行う設定。管理者を追加するたびに必要なわけではない
  • 管理者を追加したい場合は Cloudflare Access の Policy の Include ルールにメールアドレスを1行追加するだけ。Gmail に限らず Google アカウントであればどのドメインでも登録できる