はじめに
皆さんご存知の通り、ECS Fargate は タスク定義で Secrets Manager と連携し、自動で環境変数にSecret値をセットすることが可能です。
Amazon ECS の Secrets Manager シークレットを使用した機密データの指定
利用方法は簡単でタスク定義の環境変数で「値のタイプ」を「ValueFrom」にするだけです。
値に「シークレットの ARN」を指定した場合は Secrets Managerのシークレット全体(JSON)が環境変数にセットされます。
値に「キーまで含めたARN」を指定すると、指定したキーと値の環境変数がセットされます。
そのため、通常、タスク定義ではキーまで指定しておくことになりますが、その場合、環境変数が増えるたびにタスク定義を更新する必要があります。
一方で、CodeDeployなどではタスク定義の新しい環境変数を自動でセットする簡単な方法はありません。
そのため、CodeBuildやStepFunctionを組み合わせたり、またはIaCで更新する必要があります。
。。。。
めんどくさい。そう、めんどくさいのです!!
という訳で今回タスク定義にはSecrets ManagerのシークレットのARNを設定し、環境変数にセットされたJSON値を解析し、JSONのキー・バリューで環境変数をセットすることにしました。
早速結論
まず、今回は go のプロジェクトで利用したため Dockerfile は下記としました。
FROM golang:1.22-alpine3.20
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
WORKDIR /app
COPY . /app
RUN apk update && \
apk upgrade && \
apk add --no-cache \
jq
RUN chmod 755 /app/docker-entrypoint.sh
RUN go mod tidy
RUN CGO_ENABLED=0 GOOS=linux go build -o /tmp/main ./api
EXPOSE 1323
CMD ["/app/docker-entrypoint.sh"]
ポイントはJSONを分割するために使用する「jq」をインストールしておくこと、docker-entrypoint.sh を作成しておくことです。
次にdocker-entrypoint.sh は下記のようにしました。
#!/bin/sh
echo $SECRETS_JSON | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" > ".env"
while IFS="=" read -r key value; do
key=$(echo $key | tr -d '[:space:]')
export ${key}="${value}"
done < ".env"
rm ".env"
/tmp/main
docker-entrypoint.shの作成はかなり時間がかかりました。
まず、「#!/bin/sh」である必要がありました。bash や zh などは alpine ではインストールされていないらしく、docker-entrypoint.sh が見つからない(no such file or directory)と言われてしまいます。
docker run -it xxxx ls で確認してもファイルあるじゃん!!となっていたので気づくまでに、かなり時間がかかりました。
次に、JSONファイルからKey=Valueのセットのファイル(ここでは.env)を作成します。
これは次のwhileで利用するためですが、例えば下記のような書き方はダメでした。
echo $SECRETS_JSON | jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" while IFS="=" read key value; do
key=$(echo $key | tr -d '[:space:]')
export ${key}="${value}"
done
これはパイプ「|」を利用していることが問題で、while内のexportで設定した環境変数が外に反映されないためです。
そのため、先にファイルを作成することでパイプ「|」を利用しないようにしました。
最後にタスク定義の環境変数は下記で設定しておきます。
キーがSECRETS_JSONでSecretsを選択し、値が Secrets ManagerのシークレットのARN です。
"secrets": [
{
"name": "SECRETS_JSON",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxx:secret:xxxxxx/xxxxxxx"
}
],
まとめ
以前から環境変数をいい感じに設定できないかなぁと思ってましたがこれで自動的に設定されるようになりました。
アプリケーション起動時に Secrets manager から取得してましたが、ビジネスロジックではないため悶々とさせられてましたが開放されてスッキリしました。
もっと良い方法があればぜひ教えてください!!