DBの接続情報・APIキーなどの秘匿情報は、git管理下に置くべきではないですが、皆さんはどのようなに管理しているでしょうか?
先日のAWS Summit Tokyo 2017のDMM様の事例で、EC2 System Managerパラメータストアの紹介がありましたので、使ってみました。
※ タイトルにRailsとついてますが、特にRailsに依存する内容ではありません。
EC2 SystemManager パラメータストアとは
簡単に言うと、key/value形式のパラメータをAWSで集中管理できる仕組みだと理解しています。
主に、以下の特徴があります。
- AWS API、CLIを利用してアクセス可能
- KMSを利用してパラメータ値の暗号化が可能
- IAMを利用して、各パラメータへのアクセス権を細かく制御可能
管理コンソールからの登録
EC2 Managemtn Consoleの左下に、Parameter Storeのメニューが有ります。Parameter Storeへアクセスするには、事前に、IAM Policyの「AmazonSSMFullAccess」を付与しておきます。 ( AmazonSSMFullAccessは、他の権限も含まれているため、厳密に権限管理する場合は、独自にポリシーを作成したほうが良いかと思います)
登録画面は、至ってシンプルです。この画面で登録するだけで、AWS CLI等で参照できるようになります。
AWS CLIからの参照
EC2インスタンスから、AWS CLIを使ってアクセスする方法を紹介します。
「AmazonSSMReadOnlyAccess」PolicyをAttachしたIAM Roleを作成し、EC2に割り当てておきます。
以下のコマンドでパラメータの取得可能です。
aws ssm get-parameters --region ap-northeast-1 --name production.db.user -> { "InvalidParameters": [], "Parameters": [ { "Type": "String", "Name": "production.db.user", "Value": "db_user" } ] }
valueだけ取得したい場合は、queryを利用して以下のようにとれます。
aws ssm get-parameters --region ap-northeast-1 --name production.db.user --query "Parameters[0].Value" --output text -> db_user
パラメータストアのアクセス制御
ポリシーを独自で作成することで、細かいアクセス制御が可能です。 以下のポリシーの場合は、productionで始まるパラメータのみにアクセス可能です。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1482841904000", "Effect": "Allow", "Action": [ "ssm:GetParameters" ], "Resource": [ "arn:aws:ssm:[region]:[AWSアカウント]:parameter/production.*" ] } ] }
パラメータの命名ルールとして、環境名やサービス名を入れておくと、環境やサービス単位で適切な制御ができると思います。
KMSを利用した暗号化
暗号化については、クラスメソッド様の記事が非常に参考になりますので、紹介だけに留めておきます。
AWS KMS で EC2 Systems Managerパラメータストアを暗号化 | Developers.IO
Railsで利用する
例えば、Railsのデータベース接続情報で利用する場合は、database.ymlで環境変数から読み込むようにします。
production: <<: *default database: db username: <%= ENV['DATABASE_USER'] %> password: <%= ENV['DATABASE_PASSWORD'] %> host: <%= ENV['DATABASE_HOST'] %> port: <%= ENV['DATABASE_PORT'] %>
Railsの起動ユーザの .bash_profileで、パラメータストアから値を取得して環境変数にセットしておけば、Railsアプリから参照できるようになります。
export DATABASE_USER=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.user --query "Parameters[0].Value" --output text) export DATABASE_PASSWORD=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.password --with-decryption --query "Parameters[0].Value" --output text) export DATABASE_HOST=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.host --query "Parameters[0].Value" --output text) export DATABASE_PORT=$(aws ssm get-parameters --region ap-northeast-1 --name production.db.port --query "Parameters[0].Value" --output text)
bash_profileに書いておくと、該当ユーザでログインするたびに毎回、パラメータストアへのアクセスが発生してしまいます。 そのため、初回アクセス時に別ファイルに書き出し、2回目以降はパラメータストアではなくファイルから読み出すようにしています。
if [ -e ~/.credentials ]; then source ~/.credentials else echo "export DATABASE_USER='"$(aws ssm get-parameters --region ap-northeast-1 --name production.db.user --query "Parameters[0].Value" --output text)"'" >> ~/.credentials echo "export DATABASE_PASSWORD='"$(aws ssm get-parameters --region ap-northeast-1 --name.production.db.password --with-decryption --query "Parameters[0].Value" --output text)"'" >> ~/.credentials echo "export DATABASE_HOST='"$(aws ssm get-parameters --region ap-northeast-1 --name production.db.host --query "Parameters[0].Value" --output text)"'" >> ~/.credentials echo "export DATABASE_PORT='"$(aws ssm get-parameters --region ap-northeast-1 --name production.db.port --query "Parameters[0].Value" --output text)"'" >> ~/.credentials source ~/.credentials fi
パラメータストアの追加・更新があった場合は、一度ファイルを削除する運用にしていますが、もう少し良い方法がないか模索中です。
まとめ
Railsでの秘匿情報を管理する方法としては、「yaml_vault + AWS KMS 」が良いと思ってましたが、EC2 System Managerのパラメータストアも手軽にセキュアな環境が構築でき非常におすすめです。EC2 System Managerは地味ですが、他にも良い機能があるので、今後は是非活用していきたいと思います。
参考
EC2 Systems Manager のパラメータストアを利用したアプリケーション環境設定の管理 | Developers.IO