cloudposse / terraform-aws-ecs-container-definition

Terraform module to generate well-formed JSON documents (container definitions) that are passed to the aws_ecs_task_definition Terraform resource
https://cloudposse.com/accelerate
Apache License 2.0
339 stars 244 forks source link

secrets_as_map causing issues with sensitive values #128

Closed syphernl closed 3 years ago

syphernl commented 3 years ago

This was originally posted as a comment on closed issue https://github.com/cloudposse/terraform-aws-ecs-container-definition/issues/125 but as this is a different problem problem a new issue would make more sense.

Running this module past v0.50.0 results in:

Error: Error in function call

  on .terraform/modules/container_grafana/main.tf line 21, in locals:
  21:   secrets_as_map      = zipmap(local.secrets_keys, local.secrets_values)
    |----------------
    | local.secrets_keys is (sensitive value)
    | local.secrets_values is (sensitive value)

Call to function "zipmap" failed: panic in function implementation: value is
marked, so must be unmarked first
goroutine 9695 [running]:
runtime/debug.Stack(0xc004da1ab8, 0x23d80e0, 0x2c41070)
    /usr/local/go/src/runtime/debug/stack.go:24 +0x9f
github.com/zclconf/go-cty/cty/function.errorForPanic(...)
    /go/pkg/mod/github.com/zclconf/go-cty@v1.8.0/cty/function/error.go:44
github.com/zclconf/go-cty/cty/function.Function.ReturnTypeForValues.func1(0xc004da20c8,

This can be reproduced using:

/test_module/main.tf:

resource "random_string" "password" {
  length  = 32
  special = false
}

output "test_password" {
  value       = random_string.password.result
  description = "Test password"
  sensitive   = true
}

/main.tf:

module "test" {
  source = "./test_module"
}

module "demo_container" {
  source          = "git::https://github.com/cloudposse/terraform-aws-ecs-container-definition.git?ref=master"
  container_name  = "demo-container"
  container_image = "nginxdemos/hello:latest"

  secrets = [
    {
      name      = "PASSWORD",
      valueFrom = module.test.test_password
    }
  ]

  environment = [
    {
      name  = "APP_ENV",
      value = "production",
    }
  ]

  port_mappings = [
    {
      containerPort = 80
      hostPort      = 80
      protocol      = "tcp"
    }
  ]

  healthcheck = {
    command     = ["CMD-SHELL", "curl -f http://localhost:80/health || exit 1"]
    retries     = 5
    timeout     = 5
    interval    = 30
    startPeriod = 30
  }
}

output "demo_container" {
  value = module.demo_container.json_map_encoded
}

It appears to be an issue in Terraform itself, I've found a few issues about it over the past months. The most recent one is https://github.com/hashicorp/terraform/issues/27954. In this particular issue it was reported as fixed, this fix was also included in Terraform v0.14.8 but this doesn't fix this particular issue with the module so I created https://github.com/hashicorp/terraform/issues/28049.

nitrocode commented 3 years ago

If I run the same thing without the test module, it works.

module "demo_container" {
  source          = "git::https://github.com/cloudposse/terraform-aws-ecs-container-definition.git?ref=master"
  container_name  = "demo-container"
  container_image = "nginxdemos/hello:latest"

  secrets = [
    {
      name      = "PASSWORD",
      valueFrom = "aaaa"
    }
  ]

  environment = [
    {
      name  = "APP_ENV",
      value = "production",
    }
  ]

  port_mappings = [
    {
      containerPort = 80
      hostPort      = 80
      protocol      = "tcp"
    }
  ]

  healthcheck = {
    command     = ["CMD-SHELL", "curl -f http://localhost:80/health || exit 1"]
    retries     = 5
    timeout     = 5
    interval    = 30
    startPeriod = 30
  }
}

output "demo_container" {
  value = module.demo_container.json_map_encoded
}

See this run

$ terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

demo_container = "{\"cpu\":0,\"environment\":[{\"name\":\"APP_ENV\",\"value\":\"production\"}],\"essential\":true,\"healthCheck\":{\"command\":[\"CMD-SHELL\",\"curl -f http://localhost:80/health || exit 1\"],\"interval\":30,\"retries\":5,\"startPeriod\":30,\"timeout\":5},\"image\":\"nginxdemos/hello:latest\",\"mountPoints\":[],\"name\":\"demo-container\",\"portMappings\":[{\"containerPort\":80,\"hostPort\":80,\"protocol\":\"tcp\"}],\"readonlyRootFilesystem\":false,\"secrets\":[{\"name\":\"PASSWORD\",\"valueFrom\":\"aaaa\"}],\"volumesFrom\":[]}"
syphernl commented 3 years ago

If I run the same thing without the test module, it works.

Yes, the problem lies in passing variables/outputs between modules. This issue is supposedly fixed in https://github.com/hashicorp/terraform/pull/28116, unfortunately it wasn't included in the 0.14.9 release. I have a feeling it will only be on 0.15.

syphernl commented 3 years ago

This problem has been resolved in Terraform 0.15.1.