── 鍵やパスワードを別ファイルに置いて読み込む方式 ── は、手軽で広く使われています。1人で手元だけなら、これで十分です。
ただし限界があります。この回は、限界がどこにあるかと、規模に応じた移行先を扱います。
1. .env の限界
手軽さと引き換えに、いくつかの性質を諦めています。問題になるまで気づきにくいのが特徴です。
| 限界 | 起きること |
|---|---|
| 平文で手元に残る | 機器が盗まれれば、そのまま読める |
| 共有が手作業 | チャットで送るという運用になりがち |
| 誰が見たか分からない | 漏れたとき、経路を追えない |
| 失効させにくい | 配った先を把握していないと回収できない |
| 誤ってコミットしやすい | 除外設定を忘れると履歴に残る |
| 環境ごとの管理が煩雑 | 本番・検証・手元で別々に配る |
2行目が実務で最も問題になります。新しく入った人に鍵を渡すとき、チャットで送ってしまう。送った記録が残り、削除しても相手の端末には残ります。しかも誰に渡したかの記録も残らないため、後から回収しようとしても対象が分かりません。 の仕組みが解決するのは、まさにこの点です。
次のいずれかに当てはまったら、見直す時期です。①共有する人が増えた ②環境が複数ある ③誰が使ったかを追う必要が出た ④機微なデータを扱い始めた。1つでも当てはまるなら、次の段階へ移る価値があります。
2. 段階がある
いきなり本格的な保管庫を導入する必要はありません。段階的に移行できます。
| 段階 | 方式 | 解決すること | 手間 |
|---|---|---|---|
| 1 | .env に置く | — | 最小 |
| 2 | OS の資格情報管理に置く | 平文で残らない | 小さい |
| 3 | 実行時に注入する | ファイルに書かない | 中 |
| 4 | 専用の保管庫から取得 | 取得記録が残る、失効できる | 大きい |
| 5 | 都度発行の一時的な認証 | 期限切れで自然に無効 | 大きい |
段階2 への移行が費用対効果が高いと思います。OS が持っている資格情報の保管機能を使うだけで、平文で手元に残らなくなります。手間はほとんど変わりません。
# 鍵を保管する(一度だけ)security add-generic-password \ -a "$USER" -s "openai-api-key" -w "sk-xxxxxxxx"
# 使うときに取り出すexport OPENAI_API_KEY=$(security find-generic-password \ -a "$USER" -s "openai-api-key" -w)
# シェルの設定に関数として書いておくと、必要なときだけ読めるload-secrets() { export OPENAI_API_KEY=$(security find-generic-password \ -a "$USER" -s "openai-api-key" -w 2>/dev/null) || { echo "鍵が見つかりません" >&2; return 1; } echo "読み込みました"}必要なときだけ読み込む形にしているのが要点です。常時環境変数に入れておくと、その端末で動く全てのプログラムから見えます。使うときだけ読む形にすれば、露出する範囲が狭まります。これは を、時間の軸に適用したものと考えられます。必要な範囲だけでなく、必要な間だけに絞る。
3. コミットを防ぐ
どの段階でも共通して必要なのが、誤ってコミットしない仕組みです。人の注意力に頼らない形にします。
#!/usr/bin/env bash# .git/hooks/pre-commit として置く(chmod +x を忘れずに)set -euo pipefail
# 鍵らしき文字列の形を並べるPATTERNS=( 'sk-[A-Za-z0-9]{20,}' 'AKIA[0-9A-Z]{16}' 'ghp_[A-Za-z0-9]{36}' 'BEGIN (RSA|OPENSSH|EC) PRIVATE KEY' 'password\s*=\s*["'"'"'][^"'"'"']{6,}')
found=0for p in "${PATTERNS[@]}"; do if git diff --cached -U0 | grep -nE "$p" >/dev/null 2>&1; then echo "鍵らしき文字列が含まれています: /$p/" >&2 git diff --cached -U0 | grep -nE "$p" | head -3 >&2 found=1 fidone
# .env 系のファイル自体が含まれていないかif git diff --cached --name-only | grep -E '(^|/)\.env(\.|$)' >/dev/null; then echo ".env ファイルが含まれています" >&2 found=1fi
if [[ "$found" -eq 1 ]]; then echo "" >&2 echo "意図的な場合は --no-verify を付けてください" >&2 exit 1fi完全ではありません。形が違う鍵は検出できませんし、検査を回避することもできます。それでも、最も多い事故(うっかり)は防げます。専用の検査ツールもあるので、規模が大きければそちらを検討してください。
履歴から消す作業を先にやりがちですが、順序が逆です。公開範囲によっては既に取得されている前提で、まず鍵そのものを無効化して再発行してください。履歴の掃除は、その後で構いません。
4. 環境ごとに分ける
本番・検証・手元で同じ鍵を使い回さないのは基本ですが、実際には面倒さから使い回されがちです。
| 使い回すと | 起きること |
|---|---|
| 手元と本番が同じ | 手元の誤りが本番に届く |
| 検証と本番が同じ | 検証の負荷が本番の枠を消費する |
| 人ごとに同じ | 誰の操作か区別できない |
| 失効させるとき | 全環境が同時に止まる |
1行目が最も危険です。手元で試したつもりの処理が、本番のデータを触る。エンジニアの引き継ぎ術 EP.03 で扱った「間違えたらエラーになる形」を、ここでも適用してください。本番の鍵は、手元に置かないのが基本です。
5. 保管庫を使う場合
段階4 以降 ── 専用の保管庫から取得する形 ── に移ると、いくつかの性質が手に入ります。
- 誰がいつ取得したかの記録が残る()
- 権限を外せば、その人は取得できなくなる
- 期限を設けられる
- 手元のファイルに書かなくてよい
- 環境ごとの管理が構造化される
1番目と2番目が、.env との決定的な差です。渡した鍵は回収できませんが、取得する権限は外せます。人が離れるときの処理(エンジニアの引き継ぎ術 EP.01)が、確実に完了できるようになります。
一方で、保管庫自体の運用が必要になります。誰が管理するか、止まったときにどうするか。規模に見合うかを判断してください。数人の組織で導入すると、維持のほうが負担になることがあります。
6. 判断の整理
規模ごとの現実的な選択をまとめます。
| 状況 | 現実的な選択 |
|---|---|
| 1人・手元だけ | .env + コミット防止の仕組み |
| 1人・複数環境 | OS の資格情報管理+環境ごとに分ける |
| 数人のチーム | 実行時に注入する形。共有はチャットでしない |
| 機微なデータを扱う | 保管庫(取得記録が要る) |
| 外部への公開がある | 保管庫+期限つきの認証 |
どの段階でも、コミット防止だけは必須です。1人で手元だけでも、公開リポジトリに出てしまえば同じことになります。しかも公開されている時間が短くても、自動で収集されている前提で考える必要があります。「すぐ消したから大丈夫」とは言えません。
そして、上の段階が常に正しいわけではありません。維持できない仕組みは、いずれ迂回されます。「面倒だから .env に戻す」となるくらいなら、段階2 で確実に運用するほうが安全です。
環境変数ファイル の限界は、平文で残る・共有が手作業・誰が見たか分からない・失効させにくいの4点。見直す合図は共有する人が増えたとき。OS の資格情報管理へ移すだけで平文が消え、手間はほぼ変わらない。コミット防止はどの段階でも必須。誤ってコミットしたら、履歴の掃除より先に鍵を無効化する。そして維持できない仕組みは迂回されるので、規模に見合う段階を選んでください。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。