シークレットと設定
SLACK_BOT_TOKEN と SLACK_SIGNING_SECRET を Worker のシークレットとして設定する。vars にもクライアントバンドルにも載せない。
概要
Slack 連携に必要な秘密の値は、ちょうど 2 つである。Web API を呼ぶための bot トークン(SLACK_BOT_TOKEN、xoxb-…)と、受信リクエストを検証するための signing secret(SLACK_SIGNING_SECRET)だ(リクエストの検証を参照)。どちらも wrangler secret put で設定する Worker のシークレットとして扱う。wrangler.toml の vars に置いてはいけないし、バンドラーがクライアント向け JS に取り込みうる場所から参照してもいけない。
wrangler secret put
npx wrangler secret put SLACK_BOT_TOKEN
npx wrangler secret put SLACK_SIGNING_SECRET各コマンドは値の入力を促し、それをそのままデプロイ済みの Worker へ送る。wrangler.toml にもリポジトリ内のどのファイルにも書き込まれることはない。Cloudflare のシークレットに関するドキュメントによれば、wrangler secret put は新しい Worker のバージョンを作って即座にデプロイする。段階的なロールアウトをしたい場合は、デプロイせずにバージョンだけを作る wrangler versions secret put を使う。
Slack のトークンや signing secret を vars に入れてはいけない
wrangler.toml の [vars] ブロックは平文で、リポジトリにコミットされ、Cloudflare のダッシュボードからも見える。Cloudflare 自身のガイダンスも明確だ。曰く、「Worker の Wrangler 設定ファイルで機微情報を保存するのに vars を使ってはいけない。代わりにシークレットを使うこと」。SLACK_BOT_TOKEN と SLACK_SIGNING_SECRET は、まさにこのルールが想定している類の値である。
ローカル開発: .dev.vars
wrangler dev は、wrangler.toml と同じ階層に置いた .dev.vars ファイルから、ローカル限定のシークレットを dotenv 形式で読み込む。
SLACK_BOT_TOKEN="xoxb-your-dev-workspace-token"
SLACK_SIGNING_SECRET="your-dev-workspace-signing-secret"# .gitignore
.dev.vars*.dev.vars(使っているなら .env も)は決してコミットしないこと。ローカル開発を楽にしてくれるこのファイルは、git の履歴に入った瞬間に平文のシークレットになる。Cloudflare は環境ごとのローカル上書き用に .dev.vars.<environment-name> もサポートしており、こちらは汎用の .dev.vars より先に読み込まれる。上のグロブはこうした派生形もカバーするが、.dev.vars とだけ書いた行ではカバーできない。
型付きの Env
env["SLACK_BOT_TOKEN"] のような文字列頼みの参照ではなくコンパイル時のチェックを効かせるため、両方のシークレットを Env インターフェイスに宣言しておく。
export interface Env {
SLACK_BOT_TOKEN: string;
SLACK_SIGNING_SECRET: string;
// ... other bindings: KV, D1, etc.
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// env.SLACK_BOT_TOKEN and env.SLACK_SIGNING_SECRET are typed strings here
return await handleRequest(request, env, ctx);
},
} satisfies ExportedHandler<Env>;プロジェクトが wrangler.toml から型を生成している場合(wrangler types)、そこに宣言されたシークレットは生成後の Env に暗黙的に含まれる。とはいえシークレットが wrangler.toml に宣言されることはない(宣言されるのは vars とバインディングだけだ)ため、Slack のシークレットに関しては上のように Env のフィールドを手で書くのが通常の道筋になる。
漏洩したトークン、期限切れのトークンを差し替える
wrangler secret put SLACK_BOT_TOKEN をもう一度実行すれば古い値は上書きされ、即座にデプロイされる。Worker 側に「失効」という別ステップは存在しない。まず Slack のアプリ管理コンソールでトークンをローテーションし(漏洩が確定しているなら差し替え直後でもよい)、同じコマンドで新しい値を push する。
つまずきどころ
varsとシークレットはコードから見ると区別がつかない -- どちらでもenv.SLACK_BOT_TOKENと書く。違いはその値がどうやってそこに入ったかだけにある。コードは警告してくれないので、宣言の仕方を最初から正しくしておくこと。.dev.varsの値は本番には届かない -- あくまでwrangler devのためだけに存在する。.dev.varsに新しいシークレットを足したあとwrangler secret putを忘れる、というのが「ローカルでは動くのに本番で 500」の典型パターンである。ダッシュボードで設定したシークレットと CLI で設定したシークレットは、動作としてはまったく同じ -- ただしプロジェクトごとに、どちらか一方だけを信頼できる情報源として扱うべきだ。そうしないと、環境をまたいで両者が静かに食い違っていく。
「プレビュー」デプロイからも本番のシークレットは見える。 CI が明示的に、独自のシークレットを持つ別の Worker 環境へプレビュービルドをデプロイしているのでないかぎり、同じ Worker のプレビューバージョンはシークレットを含む本番のバインディングを共有する。専用の環境を実際に用意したのでないかぎり、PR のプレビューが隔離されたワークスペースのトークンで動いていると思い込まないこと。