シークレットとキーの管理
このページで分かること
- シークレットの一覧(保存場所と、失ったときの影響)と、シークレットの値を
astro.config.mjs・wrangler.jsonc・import.meta.envに書かないこと EMDASH_ENCRYPTION_KEYは現時点でデータを暗号化しないこと、自動で生成されるプレビュー用の秘密鍵とIPのソルト、セッションとAPIトークンの扱い- 外部サービスの資格情報、プラグインの秘密情報(データベースに暗号化されずに保存される)、CLIの資格情報、ローテーションの早見表
このページの目次
この一覧を使って、どの値を実行環境に置くか、どの値がデータベースに生成されるか、どの値がプラグインによって保存されるかを判断します。各セクションでは、ローテーションが稼働中のサイトにどう影響するかも説明します。
Node.jsでは、実行時のシークレットをホスティング環境のシークレット管理機能に置き、プロセスの起動時に process.env に入るようにします。Workerでは wrangler secret put を使います。シークレットの値を astro.config.mjs、wrangler.jsonc、import.meta.env に書かないでください。Viteがビルド時の値をサーバーのバンドルに埋め込むことがあります。
概要
| シークレット | 発行元 | 保存場所 | 失ったときの影響 |
|---|---|---|---|
EMDASH_ENCRYPTION_KEY |
運用者(emdash secrets generate) |
環境変数/Workerのシークレットのみ | 現時点ではデータへの影響なし。EmDashは形式を確認するだけ |
| プレビュー用の秘密鍵 | 自動生成(環境変数で上書き可) | options テーブル(emdash:preview_secret) |
発行済みのプレビューリンクが使えなくなる。新しいリンクは問題なし |
| IPのソルト | 自動生成(環境変数で上書き可) | options テーブル(emdash:ip_salt) |
コメントのレート制限の、過去からの連続性がリセットされる |
| セッションとAPIトークン | セッション/トークンごとに生成 | セッションストア/データベース(ハッシュのみ) | なし。平文は保存されない |
| OAuthプロバイダーの資格情報 | 自分(GoogleやGitHubのコンソール) | 環境変数 | 置き換えるまで、そのプロバイダーでのログインができなくなる |
| Turnstileのシークレット | 自分(Cloudflareのダッシュボード) | 環境変数 | コメントのCAPTCHAの検証に失敗する |
| S3の資格情報 | 自分(ストレージのプロバイダー) | 実行環境 | 置き換えるまで、メディアのアップロード/ダウンロードに失敗する |
| プラグインの秘密情報 | 自分(管理画面の設定画面) | データベース(プラグインの設定/ストレージ) | 管理画面で入力し直す |
| CLIの資格情報 | emdash login/emdash plugin publish のデバイスフロー |
~/.config/emdash/auth.json(モード0600) |
デバイスフローをもう一度実行する |
| レジストリCLIの資格情報 | emdash-plugin のatproto OAuth |
~/.emdash/oauth/、~/.emdash/credentials.json(モード0600) |
もう一度ログインする。IDは自分のPDSにある |
やさしい解説
WordPressでは、wp-config.php に認証用のキーやソルトを書いておきます。EmDashでは、秘密の値の置き場所が種類ごとに分かれています。自分で用意するもの(GoogleやGitHubでのログイン、S3の資格情報など)は、ホスティングのシークレット管理機能や wrangler secret put で環境変数として渡します。プレビュー用の秘密鍵やIPのソルトはEmDashが自動で作り、データベースに保存します。どの場合も、値を astro.config.mjs や wrangler.jsonc に直接書かないことが共通のルールです。
暗号化キー
EMDASH_ENCRYPTION_KEY は現時点で、プラグインの秘密情報もほかの保存データも暗号化しません。この変数が設定されている場合、EmDashは起動時にその形式を確認します。値の形式が正しくない場合は運用者向けのログメッセージが出力されますが、サイトは引き続きリクエストを処理します。
次のコマンドは、正しい形式の値を生成します。デプロイでこの変数を使う場合は、実行環境またはWorkerのシークレットに保存します。
npx emdash secrets generate
# emdash_enc_v1_<43 base64url chars>
# Cloudflare:
wrangler secret put EMDASH_ENCRYPTION_KEY
形式は、emdash_enc_v1_ のあとに、32バイトのランダムな値をパディングなしのbase64urlで続けたものです。値は運用者が用意するもので、データベースには保存されません。この値に依存する保存データはないため、失っても現時点ではデータの復旧に影響はありません。
自動生成されるサイトのシークレット
2つのシークレットは、最初に使われたときに自動で生成され、options テーブルに保存されます。そのため、リクエスト、デプロイ、isolateをまたいでも同じ値が使われます。生成はアトミックに処理されるため、コールドスタートが同時に起きても、値は1つにまとまります。
プレビュー用の秘密鍵
プレビューURLに署名(HMAC)します。emdash:preview_secret として保存され、32バイトのランダムな値をbase64urlにしたものです。
- 上書き:複数のプロセスで同じ秘密鍵を使う必要がある場合や、監査のために値を固定したい場合は、
EMDASH_PREVIEW_SECRET(旧名の別名:PREVIEW_SECRET)を設定します。保存された値より、常に環境変数が優先されます。 - ローテーション:
emdash:preview_secretの行を削除(または環境変数を変更)して、再デプロイします。影響:以前に発行したプレビューリンクの検証が通らなくなります。ほかに壊れるものはありません。次のプレビューのリクエストで、新しい秘密鍵が生成されます(または環境変数から読み込まれます)。 - 失った場合:復旧できなくなるものはありません。プレビューリンクは、もともと短時間だけ使う設計です。
プレビューURLの作り方と検証方法は、プレビューのガイドを参照してください。
IPのソルト
コメントのレート制限に使う、コメント投稿者のIPアドレスのSHA-256ハッシュ(コメントの ip_hash)に加えるソルトです。emdash:ip_salt として保存されます。サイトごとに異なるため、別々のEmDashのインストールの間でハッシュを突き合わせることはできません。
- 上書き:
EMDASH_IP_SALTを設定します。後方互換性のため、EMDASH_AUTH_SECRET/AUTH_SECRETも参照されます。以前からこれらの値でソルトを作っていたインストールでは、ハッシュが変わりません。 - ローテーション:環境変数を変更するか、
emdash:ip_saltの行を削除します。影響:新しく投稿されたコメントのハッシュが別の値になるため、全員のレート制限のカウントがやり直しになります。既存のコメントと、保存済みのハッシュは変更されません。 - 失った場合:データは失われません。レート制限の連続性がリセットされるだけです。
セッションとAPIトークン
- セッションは、Astroのセッションストア(CloudflareではWorkers KV、Node.jsではファイルシステム)を使います。Cookieには中身を持たないセッションIDが入り、管理が必要な署名用のシークレットはありません。セッションを終えるにはログアウトします。全員にもう一度ログインさせるには、セッションストア(KVの名前空間など)を消去します。
- APIトークン(接頭辞
ec_pat_、ec_oat_、ec_ort_)は、中身を持たない256ビットのランダムな値です。保存されるのはSHA-256ハッシュだけです。平文は作成時に一度だけ表示されます。ローテーションするには、管理画面でトークンを取り消し、作り直します。 - 招待、マジックリンク、アカウント復旧用のトークンは、用途が1つに限られ、
auth_tokensにSHA-256ハッシュとして保存され、有効期限があります(招待は7日、マジックリンクは15分)。
あらかじめバックアップやローテーションをしておくものはありません。データベースが漏えいしても見えるのはハッシュだけで、どのトークンも管理画面から取り消しや再発行ができます。
自分で用意するサービスの資格情報
外部サービスの資格情報は環境変数から読み込まれ、データベースに書き込まれることはありません。ローテーションするには、プロバイダー側で資格情報を変更し、変数を更新して、再デプロイします。
| サービス | 変数 |
|---|---|
| Googleでのログイン | EMDASH_OAUTH_GOOGLE_CLIENT_ID、EMDASH_OAUTH_GOOGLE_CLIENT_SECRET(または接頭辞なしの別名) |
| GitHubでのログイン | EMDASH_OAUTH_GITHUB_CLIENT_ID、EMDASH_OAUTH_GITHUB_CLIENT_SECRET(または接頭辞なしの別名) |
| マーケットプレイスへの公開(CI) | EMDASH_MARKETPLACE_TOKEN |
| Turnstile(コメント) | EMDASH_TURNSTILE_SECRET_KEY(または TURNSTILE_SECRET_KEY) |
| S3互換ストレージ | S3_ACCESS_KEY_ID、S3_SECRET_ACCESS_KEY、S3_ENDPOINT、S3_BUCKET、S3_REGION |
Cloudflareでは、これらを wrangler secret put で設定します。ローカルでの開発では .env に書きます。Wranglerは .dev.vars と .env のどちらか一方だけを読み込み、.dev.vars がある場合はそちらが優先されます。バインディング経由のR2は、実行時のアクセスをバインディングが許可するため、アクセスキーの変数は必要ありません。メディアストレージの選択を参照してください。
プラグインの秘密情報
プラグインが type: "secret" として宣言した設定(メール配信サービスやフォームのCAPTCHAのAPIキーなど)は、管理画面で入力し、データベースに保存されます。保存先は、options テーブルの plugin:<id>:settings:<key>、またはプラグインのキーバリューストレージです。保存した秘密情報を管理画面に表示し返すかどうかは、プラグインによって決まります。適切に作られたプラグインは、秘密情報そのものではなく「値が設定済み」であることを示すフラグだけを返します(同梱のフォームプラグインはそうしています)。
- ローテーション:プロバイダー側でキーをローテーションし、新しい値をプラグインの設定画面に貼り付けます。すぐに反映されます。
- 失った場合:管理画面で値を入力し直します。ほかにこの値に依存するものはありません。
やさしい解説
WordPressのプラグインの設定と同じく、EmDashのプラグインのAPIキーなどは管理画面で入力し、データベースに保存します。注意点は、これらの値が暗号化されずに保存されることです。データベースやそのバックアップを見られる人は、APIキーも読めます。そのため、権限を絞ったAPIキーを使い、バックアップのファイルも秘密情報と同じように扱います。
CLIの資格情報
emdash CLIは2種類の資格情報を持ち、どちらも ~/.config/emdash/auth.json(XDG_CONFIG_HOME に従います)に、所有者だけが読み書きできる権限(0600)で作成します。
- サイトのトークン:
emdash loginは、OAuthのデバイスフローで自分のEmDashのインスタンスに対して認証し、得られたトークンをインスタンスのURLごとに保存します。emdash logoutはこれを削除します。実行ごとに、--tokenまたはEMDASH_TOKENで保存済みのトークンを上書きできます。 - マーケットプレイスのトークン:
emdash plugin publishは、GitHubのデバイスフローでEmDash Marketplaceに対して認証し、得られたJWTをmarketplace:<origin>ごとに保存します。CIから公開する場合は、代わりにEMDASH_MARKETPLACE_TOKENを設定します。これは保存済みの資格情報より優先されます。
このファイルを失っても問題はありません。もう一度 emdash login(または、デバイスフローをやり直す emdash plugin publish)を実行します。
プラグインレジストリのCLIの資格情報
別のCLIである emdash-plugin(パッケージ @emdash-cms/plugin-cli)は、実験的なAT Protocolのレジストリを対象にしています。そこへの公開は、自分のAT ProtocolのID(公開者のDID)に結び付いています。サイト自体は公開用の資格情報を持たず、インストール時には、そのDIDに帰属するリリースレコードのチェックサムと照合して成果物を検証します。
- 認証にはatprotoのOAuthを使います。OAuthのセッションと状態のデータは
~/.emdash/oauth/に置かれ、公開者のID情報(DID、ハンドル、PDS)は~/.emdash/credentials.jsonにキャッシュされます。どちらも所有者だけが読み書きできる権限で書き込まれます。 - CIでは、
EMDASH_PUBLISHER_DID、EMDASH_PUBLISHER_HANDLE、EMDASH_PUBLISHER_PDSでID情報を渡します。EMDASH_REGISTRY_URLはレジストリのホストを上書きします。CIから自動でpublishする場合も、ランナー上の~/.emdash/oauth/にOAuthのセッションファイルが必要です。環境変数だけではOAuthのセッションは渡りません。 - 公開用のアクセスのローテーションや取り消しは、EmDashではなく、自分のAT Protocolのアカウント(アプリパスワードなど)で操作します。Atmosphereログインを参照してください。
ローテーションの早見表
| やりたいこと | 方法 |
|---|---|
| すべてのプレビューリンクを無効にする | options の emdash:preview_secret の行を削除する(または、上書き用の環境変数を変更する) |
| コメントのレート制限用のハッシュをリセットする | EMDASH_IP_SALT を変更する(または、options の emdash:ip_salt の行を削除する) |
| 漏えいしたAPIトークンを取り消す | 管理画面の「ユーザー」→「APIトークン」で取り消し、代わりのトークンを作成する |
| すべてのセッションを終了させる | セッションストア(Workers KVの名前空間/セッションのディレクトリ)を消去する |
| プロバイダーの資格情報を置き換える | プロバイダー側でローテーションし、環境変数を更新して、再デプロイする |
| プラグインのAPIキーを置き換える | プロバイダー側でローテーションし、管理画面のプラグインの設定に入力し直す |