概要
タイトルの通りですが、AWS Secrets ManagerからParameter StoreをTerraformで作成する方法を紹介します。
想定読者
- AWSの基礎知識をお持ちの方
- AWS Secrets Manager、Parameter Store を使った事がある方
- Terraform を使った事がある方
AWSのParameter StoreとSecrets Manager、結局どちらを使えばいいのか?比較 で両サービスが比較されているので分かりやすいです。
どういう場面で役に立つか
一見すると何の為にこんな事をするのか?普通にSecrets Managerから環境変数を取得すれば良いのでは?と思うかもしれませんが、以下の状況が揃った時に使えると思っています。
- 複数のアプリケーションをAWSアカウントで管理している
- ここでは
news-app
とweather-app
という2つのアプリケーションを例に説明します
- ここでは
- 複数のアプリケーションから同様の機密情報を参照する必要がある
- この記事では以下の2つが登録されていると仮定します。
{
"TOKEN": "DummySlackToken0001"
}
{
"API_KEY": "DummySendGridAPIKEY0001"
}
それぞれ Slack のトークンと SendGrid のAPIキーです。
このように複数のアプリケーションで使いまわす機密情報が存在すると言う前提です。
この方法であれば AWS Secrets Manager
だけに機密情報を入れておけば各アプリケーション毎のParameter Storeを動的に作成する事が可能なので、手動で管理する部分を最小限に抑える事が出来るというメリットがあります。
Terraformで aws_ssm_parameter
resourcesを使いParameter Storeを作成
以下のようにHCLを書きます。
// 既に存在するSeecretManagerリソースを参照する
// この場合AWSに {環境変数}/keitakn/slack という名前で登録されている前提
data "aws_secretsmanager_secret" "slack_secret" {
name = "${terraform.workspace}/keitakn/slack"
}
data "aws_secretsmanager_secret_version" "slack_secret" {
secret_id = "${data.aws_secretsmanager_secret.slack_secret.id}"
}
// 既に存在するSeecretManagerリソースを参照する
// この場合AWSに {環境変数}/keitakn/sendgrid という名前で登録されている前提
data "aws_secretsmanager_secret" "sendgrid_secret" {
name = "${terraform.workspace}/keitakn/sendgrid"
}
data "aws_secretsmanager_secret_version" "sendgrid_secret" {
secret_id = "${data.aws_secretsmanager_secret.sendgrid_secret.id}"
}
// terraformのExternal Data Sourceを使ってSeecretManagerのJSONをデコードする
// https://www.terraform.io/docs/providers/external/data_source.html
data "external" "slack_secret_json" {
program = ["echo", "${data.aws_secretsmanager_secret_version.slack_secret.secret_string}"]
}
data "external" "sendgrid_secret_json" {
program = ["echo", "${data.aws_secretsmanager_secret_version.sendgrid_secret.secret_string}"]
}
// デコードしたJSONを元にパラメータストアを作成する
resource "aws_ssm_parameter" "news_app_slack_token" {
name = "/${terraform.workspace}/test-app/news/slack-token"
type = "SecureString"
value = "${data.external.slack_secret_json.result["TOKEN"]}"
}
resource "aws_ssm_parameter" "news_app_sendgrid_api_key" {
name = "/${terraform.workspace}/test-app/news/sendgrid-api-key"
type = "SecureString"
value = "${data.external.sendgrid_secret_json.result["API_KEY"]}"
}
resource "aws_ssm_parameter" "weather_app_slack_token" {
name = "/${terraform.workspace}/test-app/weather/slack-token"
type = "SecureString"
value = "${data.external.slack_secret_json.result["TOKEN"]}"
}
resource "aws_ssm_parameter" "weather_app_sendgrid_api_key" {
name = "/${terraform.workspace}/test-app/weather/sendgrid-api-key"
type = "SecureString"
value = "${data.external.sendgrid_secret_json.result["API_KEY"]}"
}
${terraform.workspace}
はTerraformのworkspace名が入ります。
workspaceを以下のように定義しておけば各環境変数毎にParameter Storeを生成する事が可能です。(上記のサンプルコードの場合、Secrets Managerも環境毎に作成する必要あり)
※ workspaceの設定例
- dev
- stg
- prod
terraform apply
を実行すると以下のようにParameter Storeが生成されます。
補足
/dev/test-app/news/sendgrid-api-key
のような名前でParameter Storeを生成しているのは階層化を行う為です。
例えば以下のようにAWS-CLIを使うと news-app
用の環境変数がまとめて取得出来ます。
aws ssm get-parameters-by-path --path /dev/test-app/news --with-decryption
--with-decryption
はセキュアな文字列を復号化する為のオプションです。
他にも必要に応じて --region
や --profile
等を指定して下さい。
aws ssm get-parameters-by-path --path /dev/test-app/news --with-decryption --profile nekochans-dev --region ap-northeast-1
結果は以下の通りです。
{
"Parameters": [
{
"Name": "/dev/test-app/news/sendgrid-api-key",
"Type": "SecureString",
"Value": "DummySendGridAPIKEY0001",
"Version": 1,
"LastModifiedDate": 1552918997.781,
"ARN": "arn:aws:ssm:ap-northeast-1:000000000000:parameter/dev/test-app/news/sendgrid-api-key"
},
{
"Name": "/dev/test-app/news/slack-token",
"Type": "SecureString",
"Value": "DummySlackToken0001",
"Version": 1,
"LastModifiedDate": 1552918997.788,
"ARN": "arn:aws:ssm:ap-northeast-1:000000000000:parameter/dev/test-app/news/slack-token"
}
]
}
作成したParameter Storeの使い道
AWSのサービスなので当然ですがAWSのサービスと親和性が高いです。
主にコンテナやServerlessアーキテクチャの利用時に力を発揮します。
利用用途として参考になりそうな記事をいくつか載せておきます。
- 【祝!】FargateでもECSにごっつ簡単に環境変数に機密情報を渡せるようになりました!
- パラメータストアを使って安全なLambda関数を作成する
- CodeBuild(buildspec.yml)での環境変数指定方法あれこれまとめ
終わりに
最近EC2のアプリケーションをAWS Fargateに置き換える案件を行っており、機密情報をどう管理するか?という情報が以外と少なかったので記事にしてみました。
今回作成したサンプルコードはGitHubで公開しています。
最後まで読んで頂きありがとうございました。