🔐

Cloudflare Workers の wrangler.toml に環境変数を書かないで管理する

2022/07/18に公開

動機

wrangler initを実行するとプロジェクトの雛形が生成されますが、wrangler.toml.gitignore に含まれていないため、リポジトリに含めて運用することが想定されます。

ただ、公式ドキュメントを見る限り wrangler.tomlに環境変数として渡す値を記述する模様で、セキュアな情報をゴリゴリ書くように見えました。
ローカルの開発では良いにしても、公開することを考えると結構物騒な運用になるので、できるだけセキュアな情報を書かず、wrangler.tomlを公開して運用できないかと調べました。

最初に

調べたのは 2022 年 7 月時点です。Cloudflare Workers の Doc は随時更新されており、この情報もすぐに古くなる可能性があります。

TL;DR

  • 環境変数は.dev.vars に記述する、またはwrangler secret put <key>で設定する
  • Module Workers 構文で記述して第 2 引数から環境変数を取得する
  • 公式の GitHub Actions を利用するときは環境変数だけでなく account_id も secrets から渡す

環境変数について

ローカルで開発する際には.dev.varsに環境変数を記述することができます。よくある .env系のファイルに近しいものだと思います。記述方法もそれに似ています。

.dev.vars
API_KEY = "foobar"

https://developers.cloudflare.com/workers/wrangler/configuration/#secrets

wrangler secret put <key>で設定することもできます。デプロイ先とローカルで同じ API キーを使う場合はこちらで設定する方が良いと思います。

挙動を確認するとwrangler secret put <key>をしていても、.dev.varsが存在する場合は.dev.varsを優先するようです。

Module Workers 構文での環境変数の取り扱い

Cloudflare Workers が紹介されたばかりの頃は addEventListener を使った Service Worker 構文での書き方が紹介されましたが、現在では Module Workers 構文で記述することが推奨されています。雛形でデフォルト生成するのもこの構文です。

https://developers.cloudflare.com/workers/learning/migrating-to-module-workers/

Module Workers 構文では第 2 引数から環境変数にアクセスできます。interface Envにて環境変数を定義すると型補完が効く形でアクセスできます。

export interface Env {
  API_KEY: string
}

export default {
  async fetch(
    request: Request,
    env: Env,
    ctx: ExecutionContext
  ): Promise<Response> {
       // 補完が効く
    console.log(env.API_KEY)
    return new Response('Hello World!')
  },
}

CI/CD で運用する場合

Cloudflare Workers をデプロイするための公式の GitHub Actions があります。

https://github.com/cloudflare/wrangler-action

デプロイ先に環境変数を設定する場合は secrets で渡します。下記の例では API_KEY が環境変数です。

jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 5
    name: Deploy
    steps:
      - uses: actions/checkout@v2
      - name: Publish
        uses: cloudflare/wrangler-action@2.0.0
        with:
          apiToken: ${{ secrets.CF_API_TOKEN }}
          accountId: ${{ secrets.CF_ACCOUNT_ID }}
          secrets: |
            API_KEY
        env:
          API_KEY: ${{ secrets.API_KEY }}

ハマりポイントとしてはwrangler.tomlacccount_idを記述しないと失敗します。これに関してはドキュメントに記述がある通りです。
ただ、wrangler.tomlacccount_idを書きたくない場合は secrets を使って渡すこともできます。 accountId: ${{ secrets.CF_ACCOUNT_ID }} の箇所が該当します。

運用にもよりますが、secret 経由の方がacccount_idを漏洩させにくいのでこちらの方を優先に使った方がいいと思います。

account_idwrangler whoamiを実行すると確認できます。node_modules/.cache/wranglerにも記述されているのでそちらでも確認できます。

https://github.com/cloudflare/wrangler-action#error-no-account-id-found-quitting

また勘違いしやすいですが、account_id と api_token は別物です。api_token は下記から発行できます。

https://dash.cloudflare.com/profile/api-tokens

GitHub Actions 向けの secrets の設定はgh secret setでやることをお勧めします。

https://cli.github.com/manual/gh_secret_set

最後に

Cloudflare Workers に関しては他のサーバーレス関数と似たようなものだと思っていたので .env ではなく .dev.vars を使うというのは正直初見殺しでした。

また、関数を記述する際に環境変数を process.env.API_KEY という形式ではなく、引数から受け取るというのもちょっと癖があるように感じました。

Discussion