AWS Systems Manager パラメータストア + Chamberで機密情報を管理する
AWS Systems Manager パラメータストア(以降SSMパラメータストア)を使うとアプリケーションの設定情報や機密情報をセキュアに管理することができます。SSMパラメータストアは一般的にはAWS CLIやAWS SDKを使ってアクセスするかと思いますが、GitHub等で公開されているSSMパラメータストア用のヘルパーライブラリやツールを利用するという選択肢もあります。
本ブログ記事では、それらツールの中から、Segment社が公開しているChamberの使い方をご紹介します。
目次
Chamberとは
機密情報(シークレット)を管理するためのCLIツールです。シークレットの保存先としてSSMパラーメータストアとAmazon S3を利用できます。後者(Amazon S3)は現時点ではexperimentalのステータスということもあり、実質的にはSSMパラーメータストアの管理ツールという見方も出来るかと思います。
検証環境
- macOS:Mojave(v10.14.2)
- Chamber:v2.3.3-pre2
Chamberのインストール
ChamberはGolang製です。インストールはGitHubのReleasesからバイナリをダウンロードして適当なディレクトリに配置するだけです。
go get
でもインストールできます。
$ go get github.com/segmentio/chamber
AWS Key Management Service(KMS)の設定
SSMパラメータストアではパラメータ暗号化にKMSを利用します。
Chamberはparameter_store_key
というエイリアスのカスタマーマスターキーの利用を前提としているため、事前にこのキーを作成しておきます。
参考までに、AWS CLIでのカスタマーマスターキーの作成方法を記載します。
## カスタマーマスターキー作成 $ aws kms create-key --description "parameter store key" ## エイリアス設定 aws kms create-alias --alias-name "alias/parameter_store_key" --target-key-id "<key_id>" ## キーポリシー設定 $ aws kms put-key-policy \ --key-id "<key_id>" \ --policy-name "default" \ --policy file://policy.json
キーポリシー(policy.json)についての説明は割愛します。以下を参考に設定ください。
- AWS KMS でのキーポリシーの使用(キーポリシーの例) - AWS Key Management Service
- AWS Key Management Serviceでキーの”管理”と”利用”を分離する| DevelopersIO
なお、環境変数CHAMBER_KMS_KEY_ALIAS
でキー名を指定することで、 parameter_store_key
以外のキーを使うことも可能です。
AWSのクレデンシャルの扱い
ChamberはAWS SDK for Goを使って実装されているので、AWSのクレデンシャルの設定にはクレデンシャルファイル(~/.aws/credentials
)や、AWS_ACCESS_KEY_ID
等の環境変数が使えます。ただし、Chamberにはプロファイルを指定するオプションはありません。プロファイルを指定する場合は環境AWS_PROFILE
を利用するとよいかと思います。
またChamberはMFA有りのAssumeRoleにも対応していません。MFA有りのAssumeRoleを使いたい場合は、ChamberのREADMEで触れられているようにaws-vault等のAssumeRoleのヘルパー機能を持ったツールを使う形になります。
Chamberの使い方
ここからはChamberの具体的な使い方について触れていきます。利用できる機能(コマンドオプション)は以下の8つです。シンプルですね。
コマンドオプション | 説明 |
---|---|
write | シークレットの保存 |
list | シークレットの一覧表示 |
read | シークレットの表示 |
exec | シークレットを環境変数にセット&任意のコマンド実行 |
delete | シークレットの削除 |
history | シークレットの履歴表示 |
export | シークレットのエクスポート |
import | シークレットのインポート |
シークレットの保存
chamber write
で、引数で指定した値をSSMパラメータストアに保存します。
## chamber write <service> <key> <value> $ AWS_PROFILE=prod chamber write prod/web dbuser prod-user01
上記のコマンドを実行すると、SSMパラメータストア上では/prod/web/dbuser
というキーで値prod-user01
が保存されます。
はシークレットをまとめて管理する単位、といったイメージです。例えばWebサーバーで使用するシークレットを保存する場合は
に「web」や「prod/web」等を指定し、````に「dbuser」等を指定する使い方になります。
指定したキーがすでに存在する場合は、新しいバージョンでシークレットが保存されます。
またvalue
の代わりに-
を指定することで標準入力から値を渡すことができます。
## chamber write <service> <key> - <stdin> $ AWS_PROFILE=prod chamber write prod/web dbuser - < dbuser.txt
シークレットの一覧表示
chamber list
で保存したシークレットを一覧表示できます。
## chamber list <service> $ AWS_PROFILE=prod chamber list prod/web Key Version LastModified User dbpassword 1 01-24 12:01:28 arn:aws:iam::XXXXXXXXXXXX:user/test-user dbuser 3 01-24 12:01:18 arn:aws:iam::XXXXXXXXXXXX:user/test-user
-e
を付けるとシークレットの値も表示されます。
## chamber list -e <service> $ AWS_PROFILE=prod chamber list -e prod/web Key Version LastModified User Value dbpassword 1 01-24 12:01:28 arn:aws:iam::XXXXXXXXXXXX:user/test-user dbuser 3 01-24 12:01:18 arn:aws:iam::XXXXXXXXXXXX:user/test-user prod-user03
シークレットの参照
chamber read
で個々のシークレットを参照できます。
## chamber read <service> <key> $ AWS_PROFILE=prod chamber read prod/web dbuser Key Value Version LastModified User dbuser prod-user03 3 01-24 12:01:18 arn:aws:iam::XXXXXXXXXXXX:user/test-user
-v
で、特定バージョンのシークレットを参照することもできます。
## chamber -v <version> <service> <key> $ AWS_PROFILE=prod chamber read -v 2 prod/web dbuser Key Value Version LastModified User dbuser prod-user02 2 01-24 12:01:16 arn:aws:iam::XXXXXXXXXXXX:user/test-user
シークレットの履歴表示
chamber history
でシークレットの更新履歴を表示できます。
## chamber history <service> <key> $ AWS_PROFILE=prod chamber history prod/web dbuser Event Version Date User Created 1 01-24 11:57:13 arn:aws:iam::XXXXXXXXXXXX:user/test-user Updated 2 01-24 12:01:16 arn:aws:iam::XXXXXXXXXXXX:user/test-user Updated 3 01-24 12:01:18 arn:aws:iam::XXXXXXXXXXXX:user/test-user
シークレットを環境変数へセット&任意のコマンドを実行
これがChamberのメイン機能かと思います。chamber exec
で、SSMパラメータストアに保存したシークレットのキーと値をOSの環境変数にセット&任意のコマンドを実行できます。
## chamber exec <service...> -- <your executable> $ AWS_PROFILE=prod chamber exec prod/web -- bootstrap
例えば、SSMパラーメータストアにprod/web/dbuser
とprod/web/dbpassword
という2つのシークレットが保存されている場合、上記のコマンドを実行するとDBUSER=<シークレットの値>
とDBPASSWORD=<シークレットの値>
という環境変数がセットされ、プログラムbootstrap
が実行されます。
以下の AWS Management Tools Blogでは、具体的なユースケースとしてDockerのENTRYPOINT
にchamber exec
を利用する方法が紹介されています。
ENTRYPOINT ["chamber", "exec", "app", "--", "node", "server/boot.js
といった形でENTRYPOINTを設定することで、Dockerコンテナ起動時に「SSMパラメータストアからシークレットを取得 〜 環境変数へセット 〜 バイナリ実行」、、が一気通貫で実行できるという寸法です。Chamberはシングルバイナリなので、Dockerコンテナとの相性も良いですね(そもそもDockerコンテナでの利用を意識して開発されたツールかと思います)。
シークレットのエクスポート
chamber export
でシークレットをエクスポートできます。
## chamber export [--format <format>] [--output-file <file>] <service...> $ AWS_PROFILE=prod chamber export prod/web --output-file pord_web_secrets.json
デフォルトの出力形式はjsonです。
{ "dbpassword": "1234abcd", "dbuser": "prod-user03" }
出力形式は以下を指定できます。
- json(デフォルト)
- java-properties
- csv
- tsv
- dotenv
シークレットのインポート
chamber import
でシークレットを一括インポートできます。インポートするファイルの形式は、エクスポートのそれと同じものが利用できます。
## chamber import <service> <filepath> $ AWS_PROFILE=prod chamber import prod/web ./pord_web_secrets.json Successfully imported 2 secrets
シークレットの削除
chamber delete
でシークレットを削除できます。
## chamber delete <service> <key> $ AWS_PROFILE=prod chamber delete prod/web dbuser
まとめ
SSMパラメータストアを使う場合、シークレットの登録や参照だけであればAWS CLIで十分かもしれませんが、「シークレットを環境変数へセット&任意のコマンドを実行」が簡単に出来るのは、特にDockerコンテナでの利用を考えると非常に魅力的かと思います。
シークレット管理ツールの選択肢の一つとしてご検討ください。