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)についての説明は割愛します。以下を参考に設定ください。

なお、環境変数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が保存されます。

AWS Systems Manager Parameter Store Console

<service>はシークレットをまとめて管理する単位、といったイメージです。例えばWebサーバーで使用するシークレットを保存する場合は<service>に「web」や「prod/web」等を指定し、<key>に「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/dbuserprod/web/dbpasswordという2つのシークレットが保存されている場合、上記のコマンドを実行するとDBUSER=<シークレットの値>DBPASSWORD=<シークレットの値>という環境変数がセットされ、プログラムbootstrapが実行されます。

以下の AWS Management Tools Blogでは、具体的なユースケースとしてDockerのENTRYPOINTchamber 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含めて出力形式は以下を指定できます。

  • 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コンテナでの利用を考えると非常に魅力的かと思います。

シークレット管理ツールの選択肢の一つとしてご検討ください。