APIキーや認証情報といった機密情報を
管理・保管するためのベストプラクティス
[クイックリファレンス(PDF形式)付き]

本記事は、GitHubから流出した機密情報をリアルタイム検知するサービスを提供するGitGuardian社のホームページで公開されたレポートを日本語に翻訳したものです。

(原題)Best practices for managing and storing secrets including API keys and other credentials

[cheat sheet included]

https://blog.gitguardian.com/secrets-api-management/

はじめに

APIキーや認証情報のような機密情報の保管・管理は課題が多く、どれほど細心の注意を払った方策であっても利便性を理由に抜け道が作られてしまうケースも少なくありません。当社では機密情報や認証情報の安全確保に役立つベストプラクティス一覧をまとめてみました。機密情報の管理の場合、すべてに万能なアプローチというものは存在しません。そのためこの一覧は、方策を実施すべきか否かの判断基準となるよう複数の視点で作成されています。

暗号化されていない機密情報をGitリポジトリに保管してはならない

ありがちな誤解として、プライベートリポジトリは安全性が担保されているため、機密情報の保管場所として安全だという考えがあります。プライベートリポジトリは、機密情報保管に適した場所ではありません。

機密情報をプライベートリポジトリに保管するということが一般化しているため、プライベートリポジトリはサイバー犯罪者にとって格好の攻撃ターゲットとなっています。

さらに.gitは、いわゆる「スプロール」が前提となっています。リポジトリは新しいマシンに複製(クローン)され、新たなプロジェクトに分岐されます。プロジェクトには、過去の全履歴にアクセス権を持つ新たな開発者が出入りします。プライベートリポジトリの履歴に存在する機密情報は、同じソースから分岐した新しいリポジトリすべてにそのまま受け継がれていくことになります。

機密情報がリポジトリに入り込んだ場合、プライベート、パブリックに関係なく、その状況は情報漏えいと考える必要があります。

プライベートリポジトリにある機密情報とは、20ドル札に書き込まれたパスワードのようなものです。例えば、その20ドル紙幣を信頼できる人物に手渡したとして、結局その紙幣は、繰り返し買い物の支払いに使われ、様々なレジを経由し、最終的に多くの人の手に触れることになるのです。

Gitでgit add * コマンドを使わない

git add *やgit add .のようなワイルドカードを使うと、出力ファイルや設定ファイル、一次ソースコード等、本来gitリポジトリに取り込むべきでないファイルが安易に取り込まれてしまいます。

コミットするときに各ファイルを名前で追加し、git statusコマンドを使って追跡されているファイルと追跡されていないファイルの一覧を表示します。

git-scmより引用:

「作業ディレクトリ内のファイルのステータスは、「追跡されている」(tracked)または「追跡されていない」(untracked)のいずれかになります。

追跡されている」ファイルとは、最後のスナップショットに取り込まれたファイルです。状況によって「修正されていない」(unmodified)、「修正されている」(modified)、「staged」(ステージされた)になることもあります。つまり、「追跡されている」ファイルとは、Git側で状況を把握・管理しているファイルであり、「追跡されていない」ファイルとは、それ以外のファイルすべてということになります。」

メリット

  • どのファイルがコミットされているかを完全に管理、可視化できる
  • ソースコントロールに入り込む不要なファイルリスクが低減される
  • ファイルを追加するときに慎重さが要求される

デメリット

  • コミットするときに余分な時間を取られる
  • コミットするときに誤ってファイルを見落とす可能性がある

ヒント:早目の段階でコミットする、頻繁にコミットする、こうすることでファイルの履歴検索が容易になるだけでなく、大きな作業を効果的に分割することができるほか、ワイルドカードコマンドの使用を極力抑えることにもつながります。

機密ファイルはgitignoreに追加する

機密ファイルがgitリポジトリに取り込まれないようにするため、すべてのリポジトリを対象としたファイル、.gitignoreファイルを使用します。この.gitignoreファイルでは以下のファイルを指定します:

  • .envのような環境変数を指定したファイルや、.zshrcや.configといった設定ファイル
  • ほかの工程で出力されたファイル(アプリケーションログやチェックポイント、単体テスト/カバレッジレポート等)
  • データベースの抜粋のような「リアル」データを含むファイル(テストデータを除く)

GitHubは、便利なgitignoreテンプレートを公開しています。PythonGo用のサンプルはこちらを参照してくさい。

機密情報の検出は(目視による)コードレビューに頼らない

コードレビューで必ずしも機密情報を検出できるわけではないということを心得ておくことが肝要です。機密情報が前のバージョンのコードに紛れ込んでいる場合はとりわけ注意が必要です。コードレビューが十分な役割を果たさない理由として、レビューする側の関心が変更差分に偏りがちで、プロジェクトの履歴全体に注意が及ばない点が挙げられます。

Why a code review won't detect an deleted API key
コードレビューで、削除済みのAPIキーが見つからない「仕組み」

例えば、機密情報がある開発ブランチにコミットされ、その後削除された場合、こうした機密情報は人の目に触れなくなる、あるいはレビューする人にとって重要ではなくなります。Gitの性質上、履歴で見過ごされてしまった機密情報というのは、その後も漏えいリスクにさらされ続けることになります。そのリポジトリにアクセス権を持つ者であれば、見過ごされた機密情報を前のバージョンのコードベースで見つけることができてしまうというのがその理由です。

ヒント:基本的に、機密情報検出等の事前定義ルールを設定できるケースでは、オートメーション(自動化)を実装すべきです。人間によるレビューは、ロジックなど事前定義に向かないコードのエラーチェックなどに向いています。

リポジトリでは自動のシークレットスキャンを使用する

あらゆるベストプラクティスに従ったとしても、間違いが起こるのは常です。機密度の高い情報を扱う場合は、何らかの安全策を講じる必要があります。GitGuardianでは、プライベート、パブリックのリポジトリ両方にインストールいただける、開発者様向けのシークレットスキャンソリューションを無料で提供しています。

機密情報管理成功の秘訣は「可視性」です。問題というものは、その存在に気付かなければ、解決のための行動を起こすことはできません。シークレットスキャンを使うと、組織内のシステムを余すところなく可視化できます。

それからもう一点。どれほど優秀な機密管理システム、方策であっても、新しく生成された機密情報がコードベースに入り込むあるいは、古い機密情報が抜き出され、再度取り込まれるといった状況は阻止できないということを理解しておくことが肝要です。

メリット

  • 手動による実行が必要なツールに比べて迂回や無視といったことが難しい
  • 目視のチェックに頼るよりもはるかに速くまた正確である
  • 手動によるレビューや検索では見つからない、ログや履歴に埋もれた機密情報を検出できる
  • ライブスキャニングのため、現在有効なデータの流出すべてを取り込むことができる

暗号化されていない機密情報をSlackなどのメッセージングシステムで共有しない

不本意な機密情報流出の助長要因として、メッセージングシステムを使った機密情報の平文での送信が挙げられます。このようなシステムの場合、メッセージの安全確保については配慮されているものの、シークレット情報のような機密情報の保護については配慮されていません。

こうしたシステムは攻撃者の格好のターゲットであり、情報漏えいリスクのあるメールあるいはSlackアカウントが一つでもあれば、機密情報の宝の山が特定されてしまいます。また、組織内のシステムで機密情報が送信された場合、「機密情報を使って機密情報を見つける」手法で、サイバー犯罪者は横方向のサービス間移動が可能になってしまいます。

機密情報は安全を確保して保管する

機密情報管理に万能な解決策というものはありません。プロジェクトの規模やチームの所在地、プロジェクトのスコープなど様々な要素を考慮する必要があります。場合によっては複数のソリューションの共存が必要になることもあります。一つ一つの選択肢を慎重に検討し、目の前のニーズだけでなく、プロジェクトの成長に応じてどうスケールアップしていくかも考えるようにしてください。

Gitリポジトリ内に機密情報を保管するときは暗号化を使用する

git secretのような共有ツールを使って機密情報を暗号化したうえで、gitリポジトリに保管するという方法は、機密情報が同期されるため、チームで作業をする場合に有効です。ただし、この場合、暗号化・復号化用に別途セキュリティキーを扱う必要があるため、検討すべき問題が増えるという難点があります。こうしたセキュリティキーもまた、慎重に保管、共有する必要があり、堂々巡りの問題に陥ってしまうこともあります。

メリット

  • 機密情報が同期される

デメリット

  • 暗号化キーを安全に取り扱う必要がある
  • 監査ログがない(どの機密情報に誰がいつアクセスしたかの記録がない)
  • 役割ベースのアクセス制御(RBAC)ができない
  • アクセスのローテーションができない。アクセスのローテーションとは、キーを失効させて再配布するという意味であり、開発者が複数いる場合、gitリポジトリでこの作業を行うのは容易ではない

ローカル環境変数を使用する(可能な場合)

環境変数とは、値をアプリケーション外部に設定する動的オブジェクトの一つです。環境変数を使うことで、アプリケーションそのものに変更を加える必要がなくなるため、ローテーションがより簡単になります。また、ソースコードへの書き込みが不要になるため、機密情報をより適切に扱えるようになります。

メリット

  • コードを変更せずにデプロイバージョン間の変更が容易である
  • リポジトリにチェックインされる可能性が低い
  • シンプルかつ明確である

デメリット

  • 開発者、アプリケーションおよび/またはインフラの同期を簡単に行う方法がないため、この方法はチームで作業をする大規模環境の場合は難しい場合がある。

「Secrets as a service」ソリューションを使用する

HashiCorp VaultAWS Key Management Serviceのようなシークレット管理システムは、暗号化システムであり、機密情報の安全な保管や厳密なアクセス管理が可能です。ただし、HashiCorp Vaultのようなマネージド型シークレットソリューションは、すべての事例に有効というわけではありません。セットアップが複雑であり、しっかりとした保守が必要なためです。セットアップにも保守にも、かなりのリソース投資が必要です。

メリット

  • 機密情報の意図せぬ流出を回避できる
  • 監査ログが記録される

デメリット

  • これらは単一障害点になるため、可用性が高くセキュアなインフラにホストする必要がある
  • 連携にはすべてのコードベースを変更する必要がある
  • システムへのアクセスキーは慎重に保護する必要がある

APIのアクセスと権限を制限する

攻撃者がAPIキーのような機密情報を使っているタイミングは検出が難しいことがあります。そうした機密情報の多くが既定の権限範囲内で使われているというのがその理由です。

APIキーのアクセス許可権限を制限することで、損害の拡大や侵入の拡大だけでなく、APIが既定の権限範囲外で使われているケースを発見しやすくなります。

デフォルトのAPI権限範囲を最小に設定する

外部サービスを利用する場合、APIの権限とそのAPIが実行するタスクが一致するようにしてください。例えば、読み取り専用と読み取り/書き込み権限には適宜別のAPIを用意します。APIの多くは、アクセスできるデータの管理を強化できます。例えば、Slack APIなどは幅広い権限範囲が用意されています。このような権限範囲をうまく利用し、タスクの最小要件に対応するといったやり方は、攻撃者による機密データへのアクセスあるいはシステム侵入後の横方向の展開を阻止する上で重要です。また、1つのキーをすべてのプロジェクトで使いまわすというのも経験の浅い開発者にありがちですが、この場合、データ流出による損害リスクが大きくなるため注意が必要です。

必要に応じてIPアドレスのホワイトリストを作成する

IPアドレスのホワイトリストを作成すると、APIの不正利用を試みる攻撃者に対し、一層のセキュリティ効果が期待できます。プライベートネットワークのIPアドレスをホワイトリストに設定すると、外部サービスは信頼できるソースからのリクエストのみを受け入れるようになります。IPアドレスまたはネットワークIPアドレスを条件に合った範囲で指定するのが一般的です。

GitHubの場合、IPのホワイトリストを使用することで、信頼できないソースからのGitHubリポジトリへのアクセスをブロックできます。「IPアドレスの許可リストは、許可リストに登録されていないIPアドレスからのウェブ、API,Gitへのアクセスをブロックします。」

メリット

  • リクエストを限定して信頼できるソースを選別することで、(正規の)機密情報を使った外部ソースからの攻撃を阻止できる

デメリット

  • ソースが要求するトラフィックによって、いつも実現可能とは限らない
  • 本物の情報リクエストもブロックしてしまうことがある
  • コンスタントにメンテナンスの必要がある

有効期間の短い機密情報を使用する

APIの場合、有効期間の長いアクセストークンが一般的です。こうしたトークンの中には有効期間が無期限という場合もあります。無期限の有効期間は開発者にとっては便利であると同時に、アクセストークンが有効である限り機密情報は常にセキュリティリスクにさらされることになり、攻撃で悪用される可能性も高まります。機密情報の有効期間を短くすることで、検出を逃れた過去の流出データが脅威となるのを回避できます。つまり、攻撃者が機密情報を見つけた場合でも、その流出情報が見つからなければ攻撃者のアクセスは阻止される、ということになります。

また、APIは失効・再配布を頻繁に行うようにすることも、よい習慣であると考えられています。特に、APIの有効期限の実装が難しい場合は検討を推奨します。

あなたは従業員が何百人もいる会社の経営者です。従業員は全員、会社の鍵を持っています。鍵というものは失くなるものです。従業員が会社を辞め、新しい鍵が作られる。やがて、どの鍵がどこにあるかわからなくなってしまいます。
このように、鍵をときどき変えるということはよい習慣だと考えられています。

メリット

  • 機密情報の漏えい防止を徹底できる
  • 長期間の脅威によるリスクが軽減される

デメリット

  • 能動的な機密情報(シークレット)管理戦略が求められる

まとめ

機密情報の管理と保管は、経験豊富な開発者であっても慎重さが求められる、難しい課題の一つです。機密情報の使用方法、保管方法、共有方法、配布方法をその都度慎重に検討する必要があるためです。残念ながら、開発者の参考になる完璧なチェックリストというものは存在しません。また、方策やツール、戦略もプロジェクトによって異なるものです。とはいうものの、開発プロセス全体を通じて機密情報管理を情報に基づく能動的な戦略とするためにも、開発者が方策の効果の重要性を理解しておくことは極めて重要です。

セキュリティ関連のクイックリファレンスはほかにもあります。ぜひご活用ください。