こんにちは。決済システムでエンジニアをしている hoshino33 です。
今回は、クレデンシャル情報のハードコードを解消し、よりセキュアな管理手法へ移行した際の取り組みについてお話しします。
この改善は、元々 PCI DSS v4.0 の要件8.6.2で推奨されているベストプラクティスへの対応が目的でした。PCI DSSの詳細は割愛します。
はじめに
弊社の決済システムはC#で開発しており、AWSをインフラ基盤として利用しています。
今回の対応前は、.NET Framework環境では config
ファイル、.NET環境では json
ファイルという、一般的な形式でクレデンシャル情報が管理されていました。
対応方法の検討
対応にあたり、以下の3つの方法を検討しました。
- パスワードを暗号化する
- 環境変数に持たせる
- 環境変数以外に持たせる
結論として、「環境変数以外に持たせる」という方法を採用しました。
パスワードを暗号化する
ファイル内に平文ではなく、暗号化してパスワードを記載する方法です。
.NET Frameworkでは aspnet_regiis
ツールでファイル暗号化が可能でしたが、このツールは .NET 環境ではサポートされていません。もし採用した場合、.NET Framework と .NET でそれぞれ異なる暗号化プロセスを管理する手間が発生します。この管理の複雑さを避けるため、今回は見送りました。
環境変数に持たせる
EC2インスタンス (Windows) の環境変数にパスワードを持たせる方法です。
この方法はパスワードをコードから分離できるメリットがありますが、インスタンス数が増加した場合、一台ごとの環境変数設定作業が非常に手間になることが課題でした。この運用コストを考慮し、却下しました。
環境変数以外に持たせる
AWSが提供する AWS Systems Manager または AWS Secrets Manager の利用です。これらは機密情報を安全に保管し、必要な時にだけアプリケーションに渡すクラウドサービスです。
AWSの公式ドキュメントでは、パスワードのように更新されるべき機密情報については、AWS Secrets Manager の利用が強く推奨されています。
この推奨に基づき、AWS Secrets Managerを採用しました。これにより、パスワードを安全かつ効率的に管理できるようになります。
対応内容
AWS Secrets Managerの管理画面からシークレットを登録するだけで、利用を開始できます。余談ですが、画面上には各プログラミング言語でのサンプルコードも表示され、実装の助けになりました。
コード側では AWSSDK.SecretsManager
を利用してシークレットを実際に取得するようにしました。その際、APIを毎回実行してコストがかからないように、アプリケーション起動時に一度だけAPIを実行するよう実装を工夫しています。
また、ローカル開発時にはSecrets ManagerのAPIを実行せず、環境変数からパスワードを取得するようにしました。これにより、開発時のコスト発生を抑えています。
まとめ
AWS Secrets Managerを利用することで、クレデンシャル情報の安全な管理を容易に実現できました。
今回の改善は、直接ユーザーに見える「プロダクト機能拡張」ではないため、優先度が下がりがちです。しかし、弊社ではPCI DSS準拠を徹底しているため、セキュリティ関連の開発も重視され、開発計画に組み込まれています。
今後も、PCI DSSの有無に関わらず、セキュリティを意識した開発を続けていきたいと思います。
最後に、もしあなたのシステムでパスワードがハードコードされているのであれば、セキュリティ強化のためにも、ぜひ解消することをおすすめします。
We are hiring!!
ROBOT PAYMENTでは一緒に働く仲間を募集しています!!!