🗂

ECSタスクの環境変数をParameter Storeで管理する

2023/06/10に公開

Parameter Storeってなに?

パラメータを保存・管理してくれるAWSのマネージドサービスです。
以降は簡略化のためParameter Storeパラメータストアと表記します。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-parameter-store.html

パラメータストアでECS環境変数を管理するメリット

  • タスク定義に環境変数をベタ書きせずにすむ
    • 接続先DBのパスワード等の機密情報をAWS側で安全に管理できます。
  • 復号処理が不要
    • コンテナ側で復号処理を行う必要がありません。
  • 参照管理にIAMポリシーを使用出来る
    • 機密情報の管理にIAMポリシーを使うことが出来ます。セキュリティレベルが上がりますね。

こんなことが実現出来ます

タスク定義で以下のようにパラメータストアのArnを入力すると

コンテナ内部から環境変数として参照することが出来ます。

root@ip-10-10-2-105:/# env | grep SecretEnv
SecretEnv=Today's date is June 10th, 2023.

考慮点

いくつか考慮することがあるので、この構成を試す場合はドキュメントを確認します。

  • 稼働中のコンテナに環境変数は渡せないため、新しくデプロイする必要がある
  • Fargateでパラメータストアを使用する場合、Fargateの1.3.0以上を使用する必要がある
  • プライベートサブネットにECSタスクが存在する場合、VPCエンドポイント経由でSSMエンドポイントへアクセスする必要がある

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/secrets-envvar-ssm-paramstore.html

今回の検証内容

  • awscliでパラメータストアを設定
  • TerraformのDataでパラメータストアを読み込み、コンテナ定義から環境変数として設定する
  • タスクにECSEXECし、設定した環境変数を確認する

環境

  • awscliとTerraform,セッションマネージャープラグイン(ECSExec用)を使用します。
$ aws --version
aws-cli/2.11.2 Python/3.11.2 Linux/5.4.0-150-generic exe/x86_64.ubuntu.20 prompt/off

$ terraform --version
Terraform v1.4.6
on linux_amd64

手順

パラメータストア設定

awscliで設定します。
パスワード等の機密情報を想定し、SecureStringとします。

設定

$ aws ssm put-parameter \
    --name "/test/secret-string" \
    --description "test securestring" \
    --value "Today's date is June 10th, 2023." \
    --type SecureString

確認

$ aws ssm get-parameters \
>   --names "/test/secret-string" \
>   --with-decryption \
>   --query Parameters[].Value \
>   --output text
Today's date is June 10th, 2023.

https://dev.classmethod.jp/articles/create-rds-ssm-param-with-terraform/

設定したパラメータストアをTerraformから参照する

dataを使って参照します。
with_decryptionでsecurestringを復号してくれるため使用、
デフォルトでtrueなのですが、plaintextと区別する上でも有益だと思うので明示しておきます。

data "aws_ssm_parameter" "securestring" {
  name = "/test/secret-string"
  with_decryption = "true"
}

詳しくはこちら
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter

パラメータストアアクセス用IAMポリシー

ECSがパラメータストアにアクセスするためのIAMポリシーをタスク実行ロールにアタッチする必要があります。
タスクロールではないので注意しましょう。

data "aws_iam_policy_document" "GetParameterStore" {
  statement {
    effect = "Allow"
    actions = [
      "ssm:GetParameters",
    ]
    resources = [
      "${data.aws_ssm_parameter.securestring.arn}",
    ]
  }
}

resource "aws_iam_policy" "GetParameterStore" {
  name   = "GetParameterStore"
  path   = "/"
  policy = data.aws_iam_policy_document.GetParameterStore.json
}

resource "aws_iam_role" "task_execution_role" {
  name = "${var.system_name}_${var.environment}_task_execution_role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = { Service = "ecs-tasks.amazonaws.com" }
        Action    = "sts:AssumeRole"
      }
    ]
  })
  managed_policy_arns = [
   "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
   "${aws_iam_policy.GetParameterStore.arn}"
  ]
}

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/secrets-envvar-ssm-paramstore.html#secrets-envvar-ssm-paramstore-iam

パラメータストアのArnをコンテナ定義から使用する

わたしの環境ではコンテナ定義を外部ファイルcontainer_definitions.jsonで外だししています。
TerraformのtemplatefileでパラメータストアのArnを渡してあげます。

resource "aws_ecs_task_definition" "app" {
  container_definitions = templatefile("../../modules/app/container_definitions.json",
    {
      securestring = data.aws_ssm_parameter.securestring.arn
    }
  )

パラメータストアの値を使う場合はsecretsを使用します。

container_definitions.json
[
    {
// 略
      "secrets": [
        {
            "name": "SecretEnv",
            "valueFrom": "${securestring}"
        }
      ],

今回の場合、環境変数名をSecretEnv、その値をパラメータストアsecurestringとしています。

ECSExecする準備

本題ではないため割愛しますが、環境変数の確認のためにECSExecが実行可能でなくてはいけません。

  • aws_ecs_serviceenable_execute_command = trueとする
  • ECSExec用のIAMポリシーを作成する
  • aws_ecs_task_definitionでECSExec用のタスクロールを指定する
  • タスクの再デプロイ

といったステップを踏む必要があるので、別途対応しましょう。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html

動作確認

ここまでできれば準備完了です。
terraform applyECSExecを行い、パラメータストアの値を参照できるか確認しましょう。

$ aws ecs execute-command --cluster <cluster> \
    --task <task arn> \
    --container nginx \
    --interactive \
    --command "/bin/bash"

The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


Starting session with SessionId: ecs-execute-command-04b9bc781d0f1939a
root@ip-10-10-1-158:/#
root@ip-10-10-1-158:/# env | grep SecretEnv
SecretEnv=Today's date is June 10th, 2023.

無事できましたね。
ここまで読んでいただきありがとうございました。

参考

https://practical-aws.dev/p/container-ecs-parameter-store/

あとは公式ドキュメント群

Discussion