Cloudflare Zero TrustのAccess機能を使って、Cloudflare Workersで構築したAPIに認証を設定する
Cloudflare Workersで構築したAPIを、特定のユーザーやクライアントからのみ実行させたい場合、Cloudflare Zero TrustのAccess機能を使うことで、コード不要でAPIに認証を設定できる。
Cloudflare Workersで構築したAPIは、URLが分かれば、誰でもAPIを呼び出すことができてしまう。
特定のユーザーかクライアントからのみ実行させたい場合、APIに認証をかける必要がある。
Cloudflare Zero TrustのAccess機能を使うと、Cloudflareが管理するネットワーク上にあるサービスに対してCloudflare Dashboardで設定するだけで認証機能を付与できる。
ただし、Cloudflare Workersにデプロイしたリソース自体にはAccess機能を設定できない。
そのため、Cloudflare WorkersのリソースのURLに割り当てたCNAMEレコードのドメインに対してAccess機能を設定する必要がある。
必要なもの
- Cloudflareで管理している独自ドメイン
- Cloudflare WorkersにデプロイしたAPI
事前準備
Cloudflare Workersにデプロイするテスト用のAPIを作成する。
テスト用のAPIはHonoのスターターテンプレートを使って作ることにする。
npm create hono
コマンドを実行して、Honoのプロジェクトを生成する。
この記事ではプロジェクト名を「example-api」とする。npm create hono@latest example-api ✔ Using target directory … example-api ✔ Which template do you want to use? › cloudflare-workers cloned honojs/starter#main to /Users/chick-p/Desktop/example-api ✔ Copied project files
依存パッケージをインストールする。
cd example-api npm install
src/index.ts
を次の内容に置き換える。/hello
にGETリクエストを送信すると「Hello World」というJSONを返すエンドポイントを作成する。src/index.tsimport { Hono } from "hono"; const app = new Hono(); app.get("/hello", (c) => { return c.json( { message: "Hello World", } ); }); export default app;
npm run dev
コマンドを実行し、ローカルサーバーを起動する。npm run dev > dev > wrangler dev src/index.ts ⛅️ wrangler 3.22.2 ------------------- ⎔ Starting local server... [wrangler:inf] Ready on http://localhost:8787
/hello
に対してGETリクエストを送信し、「Hello World」というJSONが返ってくることを確認する。curl http://localhost:8787/hello {"message":"Hello World"}
npm run deploy
コマンドを実行し、APIをデプロイする。
デプロイに成功すると、https://<PROJECT_NAME>.<USER>.workers.dev/hello
にアクセスできるようになる。npm run deploy > deploy > wrangler deploy --minify src/index.ts ⛅️ wrangler 3.22.2 ------------------- Total Upload: 21.95 KiB / gzip: 8.06 KiB Uploaded example-api (1.14 sec) Published example-api (3.77 sec) https://example-api.<USER-IDENTIFER>.workers.dev Current Deployment ID: f91e0bc6-f081-4589-b4d1-9b557766eff8
デプロイしたAPIに対しても、
/hello
に対してGETリクエストを送信し、「Hello World」というJSONが返ってくることを確認する。curl https://example-api.<USER-IDENTIFER>.workers.dev/hello {"message":"Hello World"}
設定手順
本題の、Cloudflare WorkersにCloudflare Zero TrustのAccess機能を使って認証を設定する手順を説明する。
STEP1:CNAMEレコードの登録
Clouflare WorkersへデプロイしたAPIにドメインを割り当てる。
Cloudflare Dashboardにアクセスし、[Websites]を開く。
CNAMEレコードを登録するドメインを選択する。
[DNS]>[Record]の順でサイドメニューを展開し、[Add record]をクリックする。
次の内容を入力する。
- Type:CNAME
- Name:サブドメインに当たる部分
この記事では「example-api」を入力する - Target:デプロイしたCloudflare WorkerのFQDN
<PROJECT>.<USER-IDENTIFER>.workers.dev
- Proxy status:有効にする
[Save]をクリックする。
STEP2:ルートの設定
Dashboardのサイドメニューから[Workers & Pages]を開く。
デプロイしたAPIを選択する。
[Triggers]タブを選択する。
「Routes」セクションの[Add route]をクリックする。
次の内容を入力する。
- Route:CNAMEレコードに登録したドメインのBase URL
ここでは「https://example-api.<DOMAIN_NAME>/*」を入力する - Zone:NAMEレコードを登録したドメイン名
- Route:CNAMEレコードに登録したドメインのBase URL
[Add route]をクリックする
あらかじめ録されていたルートを無効化する。
<PROJECT_NAME>.<USER-IDENTIFER>.workers.dev
→<USER-IDENTIFER>.workers.dev
の[…]をクリックし、[Disable]をクリックする。
この設定をすることで、元々のCloudflare WorkersのURLにリクエストを送信しても、APIが実行されなくなる。次の2点について動作を確認する。
<PROJECT_NAME>.<USER-IDENTIFER>.workers.dev
に対するリクエストが失敗することcurl https://example-api.<USER-IDENTIFER>.workers.dev/hello error code: 1042
CNAMEレコードを登録したドメインに対するリクエストが成功すること
curl https://example-api.example.com/hello {"message":"Hello World"}
STEP3:Service Tokenの生成
Zero TrustのService Tokenを生成する。
ここで生成したService TokenのクライアントIDとクライアントシークレットをAPIのリクエストヘッダーに付与すると、APIへアクセスできるようになる。
Dashboardのサイドメニューから[Zero Trust]を開く。
(初回アクセス時はZero Trustを有効化する必要があるので、手順に沿って有効化する。)[Access]>[Service Auth]の順でサイドメニューを展開し、[Create Service Token]をクリックする。
次の内容を入力する。
- Service token name:任意の名前を入力する
この記事では「example-api」と入力する - Service Token Duration:Non-expiring
- Service token name:任意の名前を入力する
[Generate token]をクリックする。
クライアントIDとクライアントシークレットが表示されるので、メモする。
STEP4:アプリケーションの作成
Cloudflare Workersに割り当てたドメインをService Tokenと関連づける。
[Access]>[Application]の順でサイドメニューを展開し、[Add an application]をクリックする。
[Self-Hosted]をクリックする
「Configure app」画面でアプリケーションの基本設定をする。
まずは「Application Configuration」セクションで、次の内容を入力する。- Application name:任意の名前を入力する
この記事では「example-api」と入力する - Session Duration:24 hours
- Subdomain domain:CNAMEレコードに登録したサブドメイン
この記事では「example-api」を入力する - Domain:CNAMEレコードを登録したドメイン名を選択する
- Application name:任意の名前を入力する
「Application Appearance」「Tags」「Block pages」セクションはデフォルトのままにする
「Identity providers」セクションで、次の内容を入力する。
- Accept all available identity providers:無効にする
- Instant Auth:無効にする
[Next]をクリックする
「Add policies」画面でポリシーの設定をする。
まずは次の内容を入力する。- Policy name:任意の名前を入力する
この記事では「example-api」と入力する - Action:Service Auth
- Session duration:Same as application session timeout
- Policy name:任意の名前を入力する
「401 Response」を有効にする。
「Configure rules」セクションの「Include」で、次の内容を入力する。
- Selector:「Everyone」を選択する
[Add require]をクリックする。
- Selector:「Service Token」を選択する
- Value:「example-api」を選択する(作成したService Tokenの名前)
[Next]をクリックする。
「Setup」画面でそのほかの設定をする。要件に応じて設定する。
- 「CORS」セクション:すべてデフォルトのまま
- 「Cookie settings」セクション:「HTTP Only」を有効にする
- 「Additional settings」セクション:すべてデフォルトのまま
- [Add application]をクリックする。
STEP5:動作確認
最後に、作成したAPIに対して、Service Tokenを付与したリクエストを送信し、APIにアクセスできることを確認する。
まずはヘッダーを付与せずAPIにリクエストを送信すると、403エラーが返ってくることを確認する。
curl -I https://example-api.example.com/hello HTTP/2 403
STEP2でメモしたService TokenのクライアントIDとクライアントシークレットをヘッダーを付与すると、レスポンスが返ってくることを確認する。
curl https://example-api.example.com/hello \ -H 'CF-Access-Client-Id: YOUR_CLIENT_ID' \ -H 'CF-Access-Client-Secret: YOUR_CLIENT_SECRET' {"message":"Hello World"}