简体   繁体   English

如何在 terraform ecs 任务定义中使用 postgres 数据库的 aws secret manager 值

[英]how to use aws secret manager values of a postgres database in terraform ecs task definition

I have the settings.py file below of a django application using terraform, docker compose and im trying to get the value of the database stored in aws secret manager in ecs task definition我有一个 django 应用程序下面的settings.py文件,它使用 terraform、docker 组合,我试图获取存储在 ecs 任务定义中的 aws 秘密管理器中的数据库的值

settings.py设置.py

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql_psycopg2",
        "NAME": os.environ.get("POSTGRES_DB"),
        "USER": os.environ.get("POSTGRES_USER"),
        "PASSWORD": os.environ.get("POSTGRES_PASSWORD"),
        "HOST": os.environ.get("POSTGRES_HOST"),
        "PORT": 5432,
    }
}

task definition任务定义

resource "aws_ecs_task_definition" "ecs_task_definition" {
  family                   = "ecs_container"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  cpu                      = 256                      
  memory                   = 512
  execution_role_arn       = data.aws_iam_role.fargate.arn
  task_role_arn            = data.aws_iam_role.fargate.arn
  container_definitions = jsonencode([
    {
      "name"         : "ecs_test_backend",
      "image"        : "${aws_ecr_repository.ecr_repository.repository_url}:latest",
      "cpu"          : 256,
      "memory"       : 512,
      "essential"    : true,
      "portMappings" : [
        {
          containerPort = 8000
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-region": "us-east-1",
          "awslogs-group": "/ecs/ecs_test_backend",
          "awslogs-stream-prefix": "ecs"
        }
      }
      "environment"   : [
        {
          "name": "POSTGRES_DB",
          "value": "${var.POSTGRES_NAME}" <=== HERE
        },
        {
          "name": "POSTGRES_PASSWORD",
          "value": "${var.POSTGRES_PASSWORD}"  <=== HERE
        },
        {
          "name": "POSTGRES_USERNAME",
          "value": "${var.POSTGRES_USERNAME}"  <=== HERE
        },
        {
          "name": "POSTGRES_PORT",
          "value": "${var.POSTGRES_PORT}"  <=== HERE
        },
        {
          "name": "POSTGRES_HOST",
          "value": "${var.POSTGRES_HOST}"  <=== HERE
        },
      ]
    }
  ])
}

variables变量

variable "POSTGRES_PASSWORD" {
    type = string
    default = "somepassword"
}

The variables above is the same used while creating the postgres rds instance.上面的变量与创建 postgres rds 实例时使用的相同。

The configuration below var.XXX does not seem to work as the task logs return psycopg2.OperationalError: FATAL: password authentication failed for user "root" var.XXX下面的配置似乎不起作用,因为任务日志返回psycopg2.OperationalError: FATAL: password authentication failed for user "root"

It probably because its not able to read the value.这可能是因为它无法读取该值。

Is the above the correct way to grab value from AWS Secret Manager using Terraform and ECS?以上是使用 Terraform 和 ECS 从 AWS Secret Manager 获取价值的正确方法吗?

You should use the sensitive data handling feature of ECS tasks, documented here .您应该使用 ECS 任务的敏感数据处理功能,记录在此处

You would move the environment variables from the environment block of your task definition to the secrets block, and give the ARN of the secret instead of the value.您可以将环境变量从任务定义的environment块移动到secrets块,并提供机密的 ARN 而不是值。 The ECS container will then read those secrets when it starts your container, and set them in the container's environment. ECS 容器将在启动您的容器时读取这些机密,并将它们设置在容器的环境中。

I have been looking and I couldn't find any good examples to achieve this in the proper way, and while the response from @Mark B adds some context is true that some code snippets can be helpful since sometimes is more complicated to code it (with all the requirements) than the theoretical explanation.我一直在寻找,但我找不到任何好的例子来以正确的方式实现这一点,虽然@Mark B 的回复添加了一些上下文是正确的,但一些代码片段可能会有所帮助,因为有时编码起来更复杂(与所有要求)比理论解释。 With that said I will split into pieces what you need to complete:话虽如此,我将把你需要完成的分成几部分:

The parameter store参数存储

You need to save your secrets somewhere and the parameters store is a good place for it according AWS best practices:您需要将您的秘密保存在某个地方,根据 AWS 最佳实践,参数存储是一个很好的地方:

resource "aws_ssm_parameter" "main" {
  for_each    = var.parameters
  name        = "/path/${var.app_name}/${each.key}"
  description = "Secrets for application ${var.app_name}"
  type        = "SecureString"
  value       = each.value
}

variable "parameters" {
  type = map(any)
}

variable "app_name" {
  type = string
}

output "arns" {
  value = [for k, v in var.parameters : { name = k, valueFrom = aws_ssm_parameter.main[k].arn }]
}

(The code above creates several parameters) (上面的代码创建了几个参数)

Be sure of adding the correct permissions to your task execution role:确保为您的任务执行角色添加正确的权限:

resource "aws_iam_role_policy" "parameter_policy" {
  name = "mypolicy"
  role = aws_iam_role.your_role.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ssm:GetParameters",
        ]
        Effect   = "Allow"
        Resource = ["*"]
      },
    ]
  })
}

Be aware that the above is just an example, to follow best practices be sure to limit the resources to the arn(s) of the parameters created above.请注意,以上只是一个示例,要遵循最佳实践,请确保将资源限制为上面创建的参数的 arn(s)。

Finally how to use it终于知道怎么用了

container_definitions = <<TASK_DEFINITION
[
  {
    "name": "hello-world",
    "image": "nginxdemos/hello",
    "cpu": 1024,
    "memory": 2048,
    "essential": true,
    "secrets": ${jsonencode(module.hello-world-secrets.arns)},
    "logConfiguration": {
      "logDriver": "awslogs",
      "options": {
        "awslogs-region": "your_region",
        "awslogs-group": "hello_world",
        "awslogs-stream-prefix": "hello_world"
      }
    }
  }
]
TASK_DEFINITION

module "hello-world-secrets" {
  source   = "./modules/secrets"
  app_name = "hello-world"
  parameters = {
    hello = "world"
  }
}

You need to decide in which point create the secret / store the secret, eg on your CI/CD inject your secret and create the parameter store resource.您需要决定在哪一点创建秘密/存储秘密,例如,在您的 CI/CD 上注入您的秘密并创建参数存储资源。

Hopefully, this help someone else looking for a way of achieving this.希望这可以帮助其他人寻找实现此目标的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM