Closed13

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

not75743not75743

paramterstore内の値を使用することで、タスク定義・コンテナ定義に機密情報を記載せずにすむ
パラメータに値を格納し、それをTerraformでひっぱってくる形で試してみます

not75743not75743

パラメータストアのためのIAMポリシー

こちらに記載があります
タスク実行ロールに必要です。タスクロールではないので注意
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/secrets-envvar-ssm-paramstore.html#secrets-envvar-ssm-paramstore-iam

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameters"
            ],
            "Resource": [
                "arn:aws:ssm:<Region>:<AccountID>:parameter/test-secret-string"
            ]
        }
    ]
}

ポリシーが足りないと以下のようなエラーがタスクから吐かれます

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secrets from ssm: service call has been retried 1 time(s):
not75743not75743

確認

ECSEXECして確認します
SecretEnvという環境変数があり、中身がパラメータストアに設定した値と同じであればよいです

root@ip-10-0-15-247:/# env | grep SecretEnv
SecretEnv="Today's date is June 10th, 2023."
not75743not75743

考慮点

いくつか考慮点があります。

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

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

not75743not75743

Terraform化

メモを残していきます

TerraformでAWSアカウントとリージョンを取得する

parameterstoreはTerraformで管理しないように考えていたため、リージョンとIDを取得しました
それぞれ以下の様に取得可能です

data "aws_region" "current" {}
data "aws_caller_identity" "current" {}

data "aws_iam_policy_document" "GetParameterStore" {
  statement {
    effect = "Allow"
    actions = [
      "ssm:GetParameters",
    ]
    resources = [
      "arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter/test-secret-string",
    ]
  }
}

パラメータストアのArnに使用しています。

https://qiita.com/f96q/items/181c17459bfacf34c100
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity

not75743not75743

Terraformのdataでparameterstoreを引っ張ってくる

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

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

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

取得出来る属性はこちらを参照
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ssm_parameter

(さっきのこれ不要だったな...)

data "aws_region" "current" {}
data "aws_caller_identity" "current" {}
not75743not75743

引っ張ってきたparameter storeをcontainer definitionでも使う

templatefileを使っているので、こんな感じでcontainer_definitions.jsonに運びます
secretsでパラメータストアを扱えます

resource "aws_ecs_task_definition" "app" {
  container_definitions = templatefile("../../modules/app/container_definitions.json",
    {
      securestring = data.aws_ssm_parameter.securestring.arn
    }
  )
container_definition.json
[
    {
// 略
      "secrets": [
        {
            "name": "SecretEnv",
            "valueFrom": "${securestring}"
        }
      ],

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html

not75743not75743

ECSExec用IAMロール、ポリシー

これが無いとECSExec出来ません。
これはタスクロールなので混同することがないようにします

## Taskrole

data "aws_iam_policy_document" "ECSExec" {
  statement {
    effect = "Allow"
    actions = [
      "ssmmessages:CreateControlChannel",
      "ssmmessages:CreateDataChannel",
      "ssmmessages:OpenControlChannel",
      "ssmmessages:OpenDataChannel"
    ]
    resources = ["*"]
  }
}

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

resource "aws_iam_role" "task_role" {
  name = "${var.system_name}_${var.environment}_task_role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect    = "Allow"
        Principal = { Service = "ecs-tasks.amazonaws.com" }
        Action    = "sts:AssumeRole"
      }
    ]
  })
  managed_policy_arns = [
   "${aws_iam_policy.ECSExec.arn}"
  ]
}

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/ecs-exec.html

not75743not75743

動作確認

terraform init,plan,applyを実行後、ECSExecで環境変数を確認できればOKです

$ 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.
このスクラップは2023/06/10にクローズされました