データベースパスワードを設定ファイルに保存してはいけない理由

新しいアプリケーションを構築しているとします。初期段階では、データベース名、サーバーアドレス、APIのURLなど、すべての可変データを1つのファイルにまとめます。それをGitにコミットし、リポジトリにプッシュし、サーバーにデプロイします。すべてが1か所にまとまっていて、実用的に感じられます。そこにデータベースパスワードを追加し、さらにAPIトークン、暗号化キーも追加します。すると、その1つの設定ファイルが、システム全体を危険にさらすセキュリティリスクに変わります。

この瞬間、すべての設定データが同じではないことに気づきます。一部のデータは、漏洩すると他者にシステムの鍵を渡すことになります。そのデータをシークレットと呼びます。シークレットを通常の設定と同様に扱うことは、チームが犯す最も一般的で危険なミスの1つです。

設定とシークレットの違い

通常の設定データには、サーバー名、アプリケーションポート、フィーチャーフラグなどが含まれます。チーム外の誰かがアプリケーションがポート8080で動作していることを知っても、大惨事にはなりません。ポート番号を知っているだけではデータベースにログインできません。

シークレットは異なります。データベースパスワード、APIトークン、暗号化キーは、攻撃者にシステムを偽装させ、データにアクセスさせ、インフラを破壊させるために使用される可能性があります。シークレットが漏洩した場合の影響は即時的かつ深刻です。

それでも多くのチームは、シークレットを通常の設定と同様に扱っています。パスワードを.envファイルに入れてGitにコミットしたり、APIトークンをアプリケーション設定ファイルに保存してリポジトリにプッシュしたり、SSHキーをプロジェクトフォルダ内に保持してすべてをクラウドにバックアップしたりしています。これはチームが不注意だからではありません。通常は、その結果をまだ経験していないからです。

シークレットが漏洩すると何が起こるか

2022年には、公開リポジトリにAWSトークンが残されていたいくつかの注目すべきインシデントがありました。攻撃者はそれらのトークンを使用して暗号通貨マイニングインスタンスを起動しました。その請求額は数時間で数万ドルに達しました。他のケースでは、漏洩したデータベースパスワードにより、顧客データがダウンロードされ、ダークウェブで販売されました。

これらのインシデントは高度な攻撃から始まったわけではありません。シークレットを設定ファイルのように扱うという単純なミスから始まりました。シークレットはそこにあり、リポジトリにアクセスできる誰でも見ることができました。リポジトリが公開されると、シークレットも公開されました。

Gitの履歴はこれをさらに悪化させます。シークレットを含むファイルを削除しても、シークレットはコミット履歴に残ります。リポジトリをクローンした人は誰でもgit logを実行して、削除したと思ったパスワードを見つけることができます。特にリポジトリが共有またはフォークされている場合、Gitの履歴を完全に消去する簡単な方法はありません。

設定とシークレットの実践的な違い

設定とシークレットの違いは、日常業務やCI/CDパイプラインでの取り扱いに影響します。

誰が見ることができるか: 設定はチームのすべての開発者が見ることができます。シークレットは、絶対に必要とする人またはシステムだけが見ることができるようにすべきです。すべての開発者が本番データベースのパスワードを知る必要はありません。

どこに保存されるか: 設定はGitに保存できます。シークレットは決してGitに保存してはいけません。シークレットは、保存時と転送時に暗号化する専用のシークレットストレージシステムに属します。

どのようにローテーションされるか: 設定はめったにローテーションする必要がありません。インフラを移行するときにサーバー名を変更する程度です。シークレットは定期的なローテーションが必要です。データベースパスワードは数か月ごとにローテーションし、漏洩の兆候があればすぐにローテーションする必要があります。

パイプラインでの処理方法: CI/CDパイプラインでは、設定はリポジトリ内のファイルから直接読み取ることができます。パイプラインはファイルを取得して使用します。シークレットには異なるアプローチが必要です。パイプラインは安全なストレージシステムからシークレットを取得し、ビルドまたはデプロイプロセスに注入し、ログ、アーティファクト、デプロイされたファイルに決して表示されないようにする必要があります。

両者を混同した場合の実践的な結果

シークレットを設定のように扱うと、元に戻すのが難しい一連の問題が発生します。

まず、誰がアクセスできるかの制御を失います。シークレットがGitにある場合、リポジトリにアクセスできるすべての人がシークレットにアクセスできます。これには、契約社員、まだアクセス権を持つ元従業員、そしてリポジトリが公開されている場合は潜在的な攻撃者も含まれます。

次に、ローテーションが困難になります。シークレットが複数の設定ファイル、ブランチ、デプロイ環境に散在している場合、ローテーションするにはすべてのコピーを見つけて更新する必要があります。必ず1つ見逃し、その古いパスワードがどこかで有効なままになります。

第三に、監査証跡が壊れます。シークレットが漏洩した場合、誰がいつアクセスしたかを知る必要があります。シークレットがGitにあった場合、答えは「これまでリポジトリにアクセスしたすべての人」です。それは有用な監査証跡ではありません。

違いを見分ける簡単な方法

設定ファイルにデータを入れる前に、自問してみてください。「チーム外の誰かがこれを見たら、それを使ってシステムにアクセスできるか?」

答えが「いいえ」なら、それはおそらく設定です。サーバー名、ポート番号、フィーチャーフラグ、ログレベルは設定です。

答えが「はい」なら、それはシークレットです。データベースパスワード、APIトークン、SSHキー、暗号化キー、サービスアカウントの認証情報はシークレットです。

この簡単なテストで、チームが犯す一般的なミスのほとんどを防ぐことができます。

シークレット処理のための実践的なチェックリスト

次のプロジェクトをセットアップするとき、または現在のプロジェクトをレビューするときは、このチェックリストを実行してください。

  • すべてのシークレットはGitの外部に保存されていますか?専用のシークレットマネージャーまたはボールトを使用してください。
  • シークレットは実行時に注入され、イメージやアーティファクトに焼き付けられていませんか?
  • CI/CDパイプラインは、リポジトリファイルではなく、安全なソースからシークレットを取得していますか?
  • シークレットはログ、エラーメッセージ、デバッグ出力から除外されていますか?
  • シークレットの種類ごとにローテーションスケジュールがありますか?
  • 漏洩が疑われる場合にすぐにシークレットをローテーションするプロセスはありますか?
  • 特定の人やシステムに対して、他の人やシステムに影響を与えずにシークレットへのアクセスを取り消せますか?

まとめ

あるデータが、他の誰かにあなたやあなたのシステムを偽装するために使用される可能性がある場合、それは設定ではありません。それはシークレットです。異なる方法で扱ってください。別々に保存してください。定期的にローテーションしてください。そして、決してGitにコミットしないでください。この教訓を苦い経験から学ぶコストは、最初から正しく行う努力よりもはるかに高くなります。