Cloudflare Zero Trust の Access 機能 を使って、Cloudflare Workers で構築した API に認証を設定する

Posts

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 のスターターテンプレートを使って作ることにする。

  1. 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
    
  2. 依存パッケージをインストールする。

    cd example-api
    npm install
    
  3. src/index.ts を次の内容に置き換える。
    /hello に GET リクエストを送信すると「Hello World」という JSON を返す エンドポイントを作成する。

    src/index.ts
    import { Hono } from "hono";
    
    const app = new Hono();
    
    app.get("/hello", (c) => {
      return c.json(
        {
          message: "Hello World",
        }
      );
    });
    
    export default app;
    
  4. 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
    
  5. /hello に対して GET リクエストを送信し、「Hello World」という JSON が返ってくることを確認する。

    curl http://localhost:8787/hello
    
    {"message":"Hello World"}
    
  6. 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
    
  7. デプロイした 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 にドメインを割り当てる。

  1. Cloudflare Dashboard にアクセスし、[Websites]を開く。

  2. CNAME レコードを登録するドメインを選択する。

  3. [DNS] > [Record] の順でサイドメニューを展開し、[Add record] をクリックする。

  4. 次の内容を入力する。

    • Type:CNAME
    • Name:サブドメインに当たる部分
      この記事では「example-api」を入力する
    • Target:デプロイした Cloudflare Worker の FQDN
      <PROJECT>.<USER-IDENTIFER>.workers.dev
    • Proxy status:有効にする

    スクリーンショット:CNAME レコードの設定項目を入力している

  5. [Save]をクリックする。

STEP2:ルートの設定

  1. Dashboard のサイドメニューから[Workers & Pages]を開く。

  2. デプロイした API を選択する。

  3. [Triggers] タブを選択する。

  4. 「Routes」セクションの[Add route]をクリックする。

  5. 次の内容を入力する。

    • Route:CNAME レコードに登録したドメインの Base URL
      ここでは「https://example-api.<DOMAIN_NAME>/*」を入力する
    • Zone:NAME レコードを登録したドメイン名

    スクリーンショット:ルートの設定項目を入力している

  6. [Add route]をクリックする

  7. あらかじめ録されていたルートを無効化する。
    <PROJECT_NAME>.<USER-IDENTIFER>.workers.dev<USER-IDENTIFER>.workers.dev の […] をクリックし、[Disable]をクリックする。
    この設定をすることで、元々の Cloudflare Workers の URL にリクエストを送信しても、API が実行されなくなる。

    スクリーンショット:すでに登録されていたルートが解除されている

  8. 次の 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 へアクセスできるようになる。

  1. Dashboard のサイドメニューから[Zero Trust]を開く。
    (初回アクセス時は Zero Trust を有効化する必要があるので、手順に沿って有効化する。)

  2. [Access] > [Service Auth] の順でサイドメニューを展開し、[Create Service Token] をクリックする。

  3. 次の内容を入力する。

    • Service token name:任意の名前を入力する
      この記事では「example-api」と入力する
    • Service Token Duration:Non-expiring
  4. [Generate token]をクリックする。

  5. クライアント ID とクライアントシークレットが表示されるので、メモする。

    スクリーンショット:クライアントIDとクライアントシークレットが表示されている

STEP4:アプリケーションの作成

Cloudflare Workers に割り当てたドメインを Service Token と関連づける。

  1. [Access] > [Application] の順でサイドメニューを展開し、[Add an application] をクリックする。

  2. [Self-Hosted] をクリックする

  3. 「Configure app」画面でアプリケーションの基本設定をする。
    まずは「Application Configuration」セクションで、次の内容を入力する。

    • Application name:任意の名前を入力する
      この記事では「example-api」と入力する
    • Session Duration:24 hours
    • Subdomain domain:CNAME レコードに登録したサブドメイン
      この記事では「example-api」を入力する
    • Domain:CNAME レコードを登録したドメイン名を選択する

    スクリーンショット:Application Configurationの設定項目が表示されている

  4. 「Application Appearance」「Tags」「Block pages」セクションはデフォルトのままにする

  5. 「Identity providers」セクションで、次の内容を入力する。

    • Accept all available identity providers:無効にする
    • Instant Auth:無効にする

スクリーンショット:Identity providersの設定項目が表示されている

  1. [Next]をクリックする

  2. 「Add policies」画面でポリシーの設定をする。
    まずは次の内容を入力する。

    • Policy name:任意の名前を入力する
      この記事では「example-api」と入力する
    • Action:Service Auth
    • Session duration:Same as application session timeout

    スクリーンショット:ポリシーの設定項目が表示されている

  3. 「401 Response」を有効にする。

  4. 「Configure rules」セクションの「Include」で、次の内容を入力する。

    • Selector:「Everyone」を選択する
  5. [Add require]をクリックする。

    • Selector:「Service Token」を選択する
    • Value:「example-api」を選択する(作成した Service Token の名前)

スクリーンショット:Service Tokenの設定項目が表示されている

  1. [Next]をクリックする。

  2. 「Setup」画面でそのほかの設定をする。要件に応じて設定する。

    • 「CORS」セクション:すべてデフォルトのまま
    • 「Cookie settings」セクション:「HTTP Only」を有効にする
    • 「Additional settings」セクション:すべてデフォルトのまま

スクリーンショット:Setupの設定項目が表示されている

  1. [Add application]をクリックする。

STEP5:動作確認

最後に、作成した API に対して、Service Token を付与したリクエストを送信し、API にアクセスできることを確認する。

  1. まずはヘッダーを付与せず API にリクエストを送信すると、403 エラーが返ってくることを確認する。

    curl -I https://example-api.example.com/hello
    
    HTTP/2 403
    
  2. 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"}