LocalStackでローカル用のAWS Secrets Managerをさくっと用意する
みなさんAWS Secrets Managerは使っていますか?
秘匿情報を簡単に管理できて便利ですよね。
ただ、ローカルでの開発中はちょっと面倒だなぁと思ったことはありませんか?私はあります。
ということで、以前から気になっていたLocalStackを試したみたところ、ローカル用のAWS Secrets Managerを簡単に用意することができたので、備忘録も兼ねて記事にしておきたいと思います(今更感はありますが)。
環境、バージョン
Docker Desktop: 4.26.1 (131620)
動作確認用
本題
1. まずはコンテナを作ってみる
今回はDocker Composeを使います。
公式ページに書いてあるのでコピペしましょう。
version: "3.8"
services:
localstack:
image: localstack/localstack
container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}"
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
environment:
- SERVICES=secretsmanager # Write the AWS services you want to use, separated by commas
- DEBUG=${DEBUG:-0}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ほぼそのままですが、今回はSecrets Managerしか使わないのでSERVICES
にsecretsmanager
のみを指定しています。
コンテナを起動したら、Secrets Managerにアクセスできるかを確認しましょう。
※AWS CLIはインストールされているものとします。
aws --endpoint-url=http://localhost:4566 secretsmanager list-secrets
上のコマンドを実行して下の結果が返って来れば成功です。
{
"SecretList": []
}
2. コンテナの起動時に値が登録されるようにする
このままでも良いのですが、いちいち値を登録するのが面倒なので、コンテナの起動時に登録されるようにしたいです。
以下に方法を3つ記載します(現状だとうまくいかないものも含めています)。
方法1. LocalStackのhookを使う
LocalStackはいくつかInitialization Hooksを用意してくれています。
今回のケースではREADY
を使うのが良さそうです。
!注意
最終的にはこの方法が最適解になるんじゃないかなと思いますが、記事作成時点ではシェルスクリプトの実行時にパーミッションエラーになってしまい実行できませんでした。
関連issue: Problem with init hooks
方法2. 初期化処理用のイメージを用意する
前述のissueの最後のコメントに書いてある方法です。
localstack
の公式イメージから新しいイメージを作ります。
FROM localstack/localstack
COPY --chown=localstack /path/to/init.sh /etc/localstack/init/ready.d/init.sh
RUN chmod u+x /etc/localstack/init/ready.d/init.sh
version: "3.8"
services:
localstack:
build: ./docker/aws <= ここを変更する
container_name: "${LOCALSTACK_DOCKER_NAME:-localstack-main}"
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
environment:
- SERVICES=secretsmanager # Write the AWS services you want to use, separated by commas
- DEBUG=${DEBUG:-0}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
方法3. 初期化処理用のコンテナを用意する
別のコンテナを起動して、そこで初期化処理を実行する方法です。
動作確認用リポジトリではこちらの方法を採用しています。
docker-compose.yml
に以下を追加します。
localstacksetup:
image: amazon/aws-cli <= AWSコマンドが使えれば他のイメージでも良いと思います
depends_on:
- localstack
restart: "no"
volumes:
- ./init:/var/tmp
entrypoint: ["sh", "-c", "sh /var/tmp/init.sh"]
3. ちゃんと動いているか確認する
コンテナを起動した後にlist-secrets
を実行します。
コンテナ作成時にregion
を指定した場合は同じregion
を指定してください(サンプルではus-west-2
を指定しています)。
aws --endpoint-url=http://localhost:4566 secretsmanager list-secrets --region us-west-2
上のコマンドを実行して下のような結果が返って来れば成功です。
{
"SecretList": [
{
"ARN": "arn:aws:secretsmanager:us-west-2:000000000000:secret:local/secret/example-sgsyiZ",
"Name": "local/secret/example",
"LastChangedDate": "2023-12-31T18:56:03.020410+09:00",
"SecretVersionsToStages": {
"cf84944c-fb19-4af0-8d44-941d552af4c2": [
"AWSCURRENT"
]
},
"CreatedDate": "2023-12-31T18:56:03.020410+09:00"
}
]
}
もう少し詳細が見たい場合はget-secret-value
を実行します。
aws --endpoint-url=http://localhost:4566 secretsmanager get-secret-value \
--secret-id local/secret/example \
--region us-west-2
下のような結果が返って来れば成功です。
{
"ARN": "arn:aws:secretsmanager:us-west-2:000000000000:secret:local/secret/example-sgsyiZ",
"Name": "local/secret/example",
"VersionId": "cf84944c-fb19-4af0-8d44-941d552af4c2",
"SecretString": "{\n \"continent\": \"Asia\",\n \"country\": \"Japan\",\n \"city\": \"Tokyo\"\n}",
"VersionStages": [
"AWSCURRENT"
],
"CreatedDate": "2023-12-31T18:56:03+09:00"
}
おまけ. シークレットの作成コマンドについて
secret-string
には"{\"user\":\"diegor\",\"password\":\"EXAMPLE-PASSWORD\"}"
のように書く以外にJSONファイルを指定することもできるので、サンプルでは後者を使用しています 。
複数人で使う時などはsecrets.json
を.gitignore
に追加しておくのが良いんじゃないかなと思っています。
aws --endpoint-url=$endpoint_url secretsmanager create-secret \
--name $secret_id \
--region $region \
--secret-string file:///var/tmp/secrets.json
{
"continent": "Asia",
"country": "Japan",
"city": "Tokyo"
}
終わりに
ここが違うよ、こうすればもっと簡単にできるよ、などありましたら、コメントをしていただけるととてもありがたいです。
Discussion