ざっくりGCP料金計算

Secret Managerを使わず本番の秘密情報をGitに入れていた話

ソースコードに書かなければOKだと思っていたが、YAMLに全部平文で書いてあった。

「このファイル、Gitに入れちゃダメなやつでは」

新しく入ったエンジニアがコードレビュー中に指摘するまで、ずっと気づいていなかった。GKEのDeployment YAMLをGitリポジトリで管理していたのだが、そのYAMLのenv sectionにデータベースのパスワード、外部APIキー、JWTの署名シークレット、Stripeの秘密鍵が全部平文で書いてあった。

チームの認識としては「ソースコードに直書きするのはNG」だった。それは徹底されていた。でも「YAMLファイルもGitで管理する=同じことだ」という認識が抜けていた。そのリポジトリはプライベートリポジトリだったが、リポジトリにアクセスできる全エンジニアが秘密情報を参照できる状態で、過去の全コミット履歴にも秘密情報が残っていた。

どれだけの情報が露出していたか

Gitのログを確認すると、DBパスワードが最初にYAMLに書かれたのは1年以上前のコミットだった。その間にリポジトリへのアクセス権を持つメンバーは数十人に上り、退職したメンバーも含まれていた。外部委託のエンジニアに一時的にリポジトリアクセスを付与したこともあった。実害があったかどうかの調査として、外部APIのアクセスログを遡って確認した。幸い不正アクセスの痕跡は見つからなかった。しかしそれは「今のところ大丈夫だった」に過ぎない。

Secret Managerへの移行と手順

GCP Secret Managerに全ての秘密情報を登録した。DBパスワード、各種APIキー、署名シークレットをそれぞれのSecretとして登録し、GKEのWorkload Identityを使ってPodが実行時にSecret Managerから値を取得する構成に変更した。YAMLには「どのSecretのどのバージョンを参照するか」だけを書き、値そのものは一切書かない。Gitの履歴から秘密情報を削除する作業は想定より手間がかかった。git filter-branchを使って履歴を書き換えたが、全メンバーにリポジトリを再クローンしてもらう必要があり、数日がかりの対応になった。合わせて全ての秘密情報をローテーションした。Secret Managerの料金は$0.06/バージョン/月程度で、安全性に対するコストとして十分に割に合う。最初から使っていれば、この一連の対応は全て不要だった。