🔑

環境変数を暗号化してgitで管理する

2025/03/02に公開

はじめに

はじめましての方ははじめまして!もひこ(@andmohiko)と申します。

チーム開発をするとき、みなさんは環境変数をどのように管理しているでしょうか。先輩からDMで渡されたり、開発ドキュメントにまとめているチームもあるのではないでしょうか。
筆者はTypeScriptでのアプリケーション開発をしているのですが、環境変数の管理方法に課題を感じることがありました。
そこで今回は、その課題をどのように解決したのかについて書いていきます。

モチベーション

アプリケーション開発では、APIキーやデータベース接続情報などの機密情報を環境変数として管理するのが一般的です。
筆者も.envファイルを利用しており、ローカル環境・開発環境・本番環境の3つの環境の.envファイルがあります。
これらは機密情報であるため、たとえプライベートリポジトリであったとしてもGitHubにアップロードしたくないという利用から、.envをGitの管理対象にはしていません。
その結果、以下のような課題が出てきました。

運用面の課題感

チーム開発において、環境変数を安全に共有・更新することがむずかしいと感じる場面が多くありました。

開発を進める中で、環境変数を追加・更新すること場面は少なくありません。
これまでは、環境変数をNotionに記載し、変更があればチームにアナウンスするという運用をしてきました。

しかし、この運用には以下のような問題があります。

  • Notionへの更新漏れが発生する
  • チームメンバーが変更を手元の.envに反映し忘れる
  • そのままデプロイした結果、一部の機能が動作しなくなるリスクがある
  • .envをGitで管理していないため、更新漏れに気付きにくい

このように、手作業による管理の限界を感じていました。

実装面の課題感

もう一つの課題として、CI/CDで環境変数を扱う際の煩雑さも気になっていました。
スーパーハムスターでは、GitHub Actionsを使ってアプリケーションをデプロイしています。
そのため、環境変数はGithub Secretsに登録していました。

しかし、ここで問題になるのは、環境変数の数が増えるほど設定する項目も増えるという点です。さらに、開発環境と本番環境のように環境が増えると、設定する変数の数も倍に増えてしまいます。

解決策の比較検討

これらの課題を解決するため、環境変数を暗号化してGitで管理するというアプローチを採用しました。
.env自体はgitignoreしますが、暗号化された.env.encはGitの管理対象とします。

暗号化の方法としてGPGを使用する方法と、OpenSSLでAES-256による暗号化を行う方法の2つが考えられます。

方法 特徴
GPG 開発者ごとにアクセス制御ができ、安全性が高い
OpenSSL 簡単でセットアップが楽だが、秘密鍵の管理が必要

どちらの方式でも、環境変数のバージョン管理が可能になり、運用面の課題は解決できそうです。
しかし、GitHub Actionsで環境変数を復号することを考えると、鍵の管理がシンプルで、復号の手順が簡単なものを選びたいです。

GPGは鍵管理が複雑だったり、復号の際に鍵のインポート手順が必要になってきます。
一方で、OpenSSLは、GitHub Secretsにパスフレーズを保存しておけば、openssl enc -aes-256-cbcコマンドですぐに復号できるという手軽さがあります。

この手軽さを考慮し、今回はOpenSSLを使った方法を選択しました。

OpenSSLを使った暗号化の仕組み

OpenSSLの enc -aes-256-cbc とは

OpenSSLでAES-256による暗号化を行うには次のコマンドを実行します。

$ openssl enc -aes-256-cbc -salt -pbkdf2 -in .env -out .env.enc -pass pass:${YOUR_SECRET_KEY}

こちらのコマンドの仕組みを分解しながら、なぜPBKDF2(Password-Based Key Derivation Function 2)を使うのかについて説明します。

このコマンドを分解すると、それぞれ以下の意味を持ちます。

オプション 説明
enc -aes-256-cbc AES-256-CBC(Cipher Block Chaining)を使用して暗号化
-salt ランダムなソルトを追加し、同じパスワードでも異なる暗号データを生成
-pbkdf2 PBKDF2 を使用して安全な鍵導出を行う
-in .env 暗号化する元のファイル
-out .env.enc 暗号化後の出力ファイル
-pass pass:YOUR_SECRET_KEY 暗号化に使うパスワード

OpenSSLのencコマンドは、AES-256などの対称鍵暗号方式を利用してデータを暗号化するために使用されます。
しかし、単純にパスワードを鍵として使うと脆弱性が生じるため、PBKDF2を利用した鍵導出が重要になります。

鍵導出(Key Derivation)とは

暗号化アルゴリズム(AES-256 など)では、暗号鍵(Encryption Key)を元にデータを暗号化します。
しかし、人間が覚えやすいパスワードを直接暗号鍵として使うのは危険です。以下の理由が挙げられます。

  • 短いパスワードは簡単に推測される
  • 同じパスワードを使い回すと、暗号化データのパターンがバレやすい
  • レインボーテーブル(Rainbow Table)攻撃を受けやすい

そこで、パスワードを安全な暗号鍵に変換する技術が鍵導出関数(KDF: Key Derivation Function)です。

-pbkdf2 の仕組みと必要性

PBKDF2はパスワードを暗号鍵に変換するための鍵導出関数(KDF)です。これを利用することで、パスワードから安全な暗号鍵を生成し、ブルートフォース攻撃に対する耐性を高めます。

PBKDF2の鍵導出の流れ

  1. ソルト(Salt)の追加
    ランダムなソルトを生成し、パスワードと組み合わせる。
    同じパスワードでも異なる暗号鍵が生成されるため、レインボーテーブル攻撃を防げる。
  2. ハッシュ関数(SHA-256 など)の適用
    ハッシュ関数(HMAC-SHA256 など)を何千回も繰り返し適用し、計算コストを増やす。
    OpenSSLのデフォルトでは10,000 回の反復を行う。
  3. 暗号鍵を生成
    導出された値をAES-256の暗号鍵として使用。

PBKDF2 の導出式

DK = PBKDF2(P, S, c, dkLen)
  • P = パスワード(Password)
  • S = ソルト(Salt)
  • c = 反復回数(Iteration Count)
  • dkLen = 生成する鍵の長さ(AES-256 の場合は 32 バイト)

従来の方法(EVP_BytesToKey)との違い

PBKDF2を使わない場合、OpenSSLはEVP_BytesToKeyという関数を使ってパスワードから鍵を導出していました。
しかし、この方法には以下のような問題があります。

従来方式(EVP_BytesToKey) PBKDF2
鍵導出の回数 1回のみ 10,000回以上
攻撃耐性 ブルートフォース攻撃に弱い 攻撃に対して強い
ソルトの使用 なし or オプション 必須
計算コスト 低い(攻撃しやすい) 高い(その分安全)

EVP_BytesToKey の問題点

  • 1回の計算しか行われない → 簡単に総当たり攻撃が可能。
  • ソルトを使わない場合がある → レインボーテーブル攻撃に弱い。
  • 計算コストが低いため、パスワードクラックが容易。

このような理由から、PBKDF2を使わないとセキュリティが低くなるため、OpenSSLでは-pbkdf2を使うことが推奨されています。

暗号化と復号の手順

それでは実際に実行するコマンドを紹介します。

暗号化する際は次のコマンドを実行します。

$ openssl enc -aes-256-cbc -salt -pbkdf2 -in .env -out .env.enc -pass pass:${キー}

復号する際は次のコマンドを実行します。

$ openssl enc -aes-256-cbc -d -salt -pbkdf2 -in .env.enc -out .env -pass pass:${キー}

.env.encから復号した.envが元の内容と一致していれば成功です🎉

運用方法

さいごに、運用方法について説明します。

環境変数を安全に管理しつつ、チーム全員がスムーズに運用できるように、以下のフローを採用します。

準備

暗号化された環境変数はGitの管理対象にしますが、環境変数自体はgitignoreしておく必要があります。
.envは環境ごとに.env.local, .env.develop, .env.productionというようにファイルが分かれています。
そこで、次のように.gitignoreを編集します。

# .gitignore

.env*
!.env*.enc

更新手順

  1. 環境変数の変更とGitへのpush
    環境変数を変更した際は、必ず暗号化してGitにpushし、Pull Requestに含めます。
  2. チームメンバーは手元に反映する
    環境変数を更新したらチームに周知し、メンバーはpullしたタイミングで手元の.envファイルを更新します。
  3. 暗号化キーは定期的に変更する
    暗号化キーは数ヶ月ごとやメンバーの入れ替わりがあったタイミングで更新するとよいかもしれません。

さいごに

環境変数の管理は、アプリケーション開発においてセキュリティと運用の両面で重要な課題です。
Gitでのバージョン管理のメリットを活かしつつ、機密情報を安全に扱うための方法としてOpenSSLを用いた環境変数の暗号化を導入しました。

同じような課題感を抱えている方はぜひ試してみてください。

Discussion