re:Invent 2016 で発表されたけど,オンプレ関連だと勝手に思い込んでいて,今まで試していなかった Amazon EC2 Systems Manager の中に「パラメータストア」というサービスがあり,試してみたらこれが非常に便利だった.簡単に言うと,任意のパラメータをパラメータストアに格納することができて,アプリケーションと環境変数を完全に切り離すことができてしまうというもの.The Twelve-Factor App を実現できるぞ!
パラメータストアとは?
- 任意のパラメータをパラメータストアに格納することができる
- データタイプは3種類ある
String
String List
Secure String
(パラメータを KMS で暗号化して格納する)
.
と_
を使うと,パラメータをグルーピングできる- IAM Role でアクセスできるパラメータグループを制御できる
パラメータストアに格納してみた
サンプルとして,4個のパラメータをパラメータストアに格納してみた.なお,キーと値は同じにした.
- パラメータグループとして
prd
とstg
を用意した - KMS の挙動を確認するため
String
とSecure String
を用意した
パラメータストアからパラメータを取得する
aws ssm get-parameters
コマンドを使うと,簡単にパラメータを取得することができる.
$ aws ssm get-parameters --name 'stg.user_id' { "InvalidParameters": [], "Parameters": [ { "Type": "String", "Name": "stg.user_id", "Value": "stg.user_id" } ] }
Secure String
の場合は,デフォルトだと KMS で暗号化された値が返ってくる(今回は例として xxxxx とした).
$ aws ssm get-parameters --name 'stg.user_pass' { "InvalidParameters": [], "Parameters": [ { "Type": "SecureString", "Name": "stg.user_pass", "Value": "xxxxx" } ] }
よって,Secure String
の場合は --with-decryption
オプションを付ける必要がある.ちなみに --with-decryption
オプションは Secure String
以外の場合は無視されるため,String
のときにも付けておけば,コマンドが統一できて良さそう.
$ aws ssm get-parameters --name 'stg.user_pass' --with-decryption { "InvalidParameters": [], "Parameters": [ { "Type": "SecureString", "Name": "stg.user_pass", "Value": "stg.user_pass" } ] }
ちなみに aws ssm get-parameters
コマンドの詳細は以下にまとまっている.
パラメータストアから取得した値を環境変数に設定する
こんな感じでスクリプトを用意すれば,簡単に The Twelve-Factor App を実現できる.便利!
$ USER_ID=$(aws ssm get-parameters --name 'stg.user_id' | jq -r '.Parameters[].Value') $ echo ${USER_ID} stg.user_id $ USER_PASS=$(aws ssm get-parameters --name 'stg.user_pass' --with-decryption | jq -r '.Parameters[].Value') $ echo ${USER_PASS} stg.user_pass
IAM Role でアクセスできるパラメータグループを制御する
まず prd.*
にアクセスできる IAM ポリシーと stg.*
にアクセスできる IAM ポリシーを用意して,IAM ロールに紐付けた.
policy-ssm-prd
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:Describe*", "ssm:Get*", "ssm:List*" ], "Resource": [ "arn:aws:ssm:ap-northeast-1:111111111111:parameter/prd.*" ] } ] }
policy-ssm-stg
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ssm:Describe*", "ssm:Get*", "ssm:List*" ], "Resource": [ "arn:aws:ssm:ap-northeast-1:111111111111:parameter/stg.*" ] } ] }
次に IAM ロールをアタッチしたインスタンスを起動して動作確認をした.以下の例は stg からパラメータストアにアクセスした状態で,prd.*
グループのパラメータにはアクセスできなかった.このように設定することで,別環境の設定が誤って取得されるリスクが無くなる.
$ aws ssm get-parameters --name 'stg.user_id' { "InvalidParameters": [], "Parameters": [ { "Type": "String", "Name": "stg.user_id", "Value": "stg.user_id" } ] } $ aws ssm get-parameters --name 'prd.user_id' An error occurred (AccessDeniedException) when calling the GetParameters operation: User: arn:aws:sts::111111111111:assumed-role/ec2-ssm-stg/i-22222222222222222 is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-northeast-1:111111111111:parameter/prd.user_id
簡単に図にすると,このようになる.
re:Invent 2016 動画
パラメータストア以外にもいろいろ機能があるので,試してみないと!
env-injector
パラメータストアから環境変数に自動的に設定をしてくれる env-injector というツールを先輩の id:okzk が実装していた.これは便利!
$ ENV_INJECTOR_PREFIX=prd env-injector printenv | egrep 'user_id|user_pass' user_id=prd.user_id user_pass=prd.user_pass $ ENV_INJECTOR_PREFIX=stg env-injector printenv | egrep 'user_id|user_pass' user_id=stg.user_id user_pass=stg.user_pass
env-injector の詳細は以下の記事を参照で!
まとめ
- Amazon EC2 Systems Manager の中にはたくさんのサービスがあった
- 「パラメータストア」は非常に便利でパラメータの格納を AWS に任せられる
- IAM Role でアクセスできるパラメータグループを制御することもできる
- クレデンシャル / データベース接続情報などの一般的なユースケース以外にも「パラメータストア」を活用できるアイデアがたくさんありそう