6

AWS Secrets Manager automatically adds a 6 character suffix to any generated secret name. Since the suffix is generated, it will be different across environments (i.e. prod, dev, etc).

The suffix is there for a good reason, but what is a best practice for looking up secrets across environments by arn when the keys will differ slightly.

Example: As part of ECS taskDef.json you can specify an arn reference like so:

{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-AbCdEf"
    }]
  }]
}

Knowing that just the suffix AbCdEf will differ between environments, what is the best approach for specifying the suffix dynamically per environment in taskDef.json?

So far I am thinking a custom env variable that can be used with string interpolation to build it like this: "arn:aws:secretsmanager:region:aws_account_id:secret:secret_name-${code}".

However, is there a more elegant way offered via AWS?

TGH
  • 38,769
  • 12
  • 102
  • 135

3 Answers3

3

The get-secret-value secret-id parameter can be either the secret ARN or the secret name. Depending on your context/interface, specifying the secret by name could be a solution.

When you need to use an ARN, for example to include the AWS account, you could use a partial ARN. Although the best practice is to use the full ARN, in this case leaving out the generated suffix is okay as long as you avoid naming your secrets ending in a hyphen plus 6 characters; per https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-secret.html:

"Do not end your secret name with a hyphen followed by six characters. If you do so, you risk confusion and unexpected results when searching for a secret by partial ARN. Secrets Manager automatically adds a hyphen and six random characters after the secret name at the end of the ARN."

For example, AWS CDK has Secret.fromSecretPartialArn, so the following should work:

new ecs.ContainerDefinition(this, 'ContainerDefinition', {
      taskDefinition: new ecs.TaskDefinition(this, 'TaskDefinition', {
        compatibility: ecs.Compatibility.FARGATE
      }),
      image: ecs.ContainerImage.fromAsset('some/path'),
      secrets: {
        SOME_SECRET: ecs.Secret.fromSecretsManager(
          secretsmanager.Secret.fromSecretPartialArn(
            this,
            'Secret',
            'arn:aws:secretsmanager:region:aws_account_id:secret:secret_name')
        )
      }
    })
rikusv
  • 646
  • 5
  • 10
2

I Think it is elegant to Injecting sensitive data as an environment variable from SSM parameter store.

{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:ssm:region:aws_account_id:parameter/parameter_name"
    }]
  }]
}

If you want to handle for multiple envs also this is elegant.

First create secrets and store in parameter store based on your envs /test/password or stage/password and prod/password and use the same in ECS task definition.

For example .. you can use env variables also.

{
  "containerDefinitions": [{
    "secrets": [{
      "name": "environment_variable_name",
      "valueFrom": "arn:aws:ssm:region:aws_account_id:prod/password"
    }]
  }]
}

Reference :- https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data-parameters.html

My IT GURU
  • 144
  • 1
  • 7
0

In order to get-secret-value you must pass in the full arn, I believe. This is true in the case of the task definition too, since it uses this same api when scheduling the task and passing secrets to the container. Therefore, you must use the list-secrets api to get that value. This can be done using any of the sdk's and will depend on how you construct this task definition. If you use cloudformation, you can output the value after creating the secret. If you use terraform, you can use the aws_secretsmanager_secret data source which makes getting this value by name trivial.

theherk
  • 6,954
  • 3
  • 27
  • 52