Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ taskDefinition.addContainer('container', {
},
secrets: { // Retrieved from AWS Secrets Manager or AWS Systems Manager Parameter Store at container start-up.
SECRET: ecs.Secret.fromSecretsManager(secret),
DB_PASSWORD: ecs.Secret.fromSecretsManager(dbSecret, 'password'), // Reference a specific JSON field
PARAMETER: ecs.Secret.fromSsmParameter(parameter),
}
});
Expand Down
10 changes: 8 additions & 2 deletions packages/@aws-cdk/aws-ecs/lib/container-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,16 @@ export abstract class Secret {
/**
* Creates a environment variable value from a secret stored in AWS Secrets
* Manager.
*
* @param secret the secret stored in AWS Secrets Manager
* @param field the name of the field with the value that you want to set as
* the environment variable value. Only values in JSON format are supported.
* If you do not specify a JSON field, then the full content of the secret is
* used.
*/
public static fromSecretsManager(secret: secretsmanager.ISecret): Secret {
public static fromSecretsManager(secret: secretsmanager.ISecret, field?: string): Secret {
return {
arn: secret.secretArn,
arn: field ? `${secret.secretArn}:${field}::` : secret.secretArn,
grantRead: grantee => secret.grantRead(grantee),
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
{
"Resources": {
"SecretA720EF05": {
"Type": "AWS::SecretsManager::Secret",
"Properties": {
"GenerateSecretString": {
"GenerateStringKey": "password",
"SecretStringTemplate": "{\"username\":\"user\"}"
}
}
},
"TaskDefTaskRole1EDB4A67": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"TaskDef54694570": {
"Type": "AWS::ECS::TaskDefinition",
"Properties": {
"ContainerDefinitions": [
{
"Essential": true,
"Image": "amazon/amazon-ecs-sample",
"Name": "web",
"Secrets": [
{
"Name": "PASSWORD",
"ValueFrom": {
"Fn::Join": [
"",
[
{
"Ref": "SecretA720EF05"
},
":password::"
]
]
}
}
]
}
],
"Cpu": "512",
"ExecutionRoleArn": {
"Fn::GetAtt": [
"TaskDefExecutionRoleB4775C97",
"Arn"
]
},
"Family": "awsecsintegsecretjsonkeyTaskDefC01C0E99",
"Memory": "1024",
"NetworkMode": "awsvpc",
"RequiresCompatibilities": [
"FARGATE"
],
"TaskRoleArn": {
"Fn::GetAtt": [
"TaskDefTaskRole1EDB4A67",
"Arn"
]
}
}
},
"TaskDefExecutionRoleB4775C97": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ecs-tasks.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"TaskDefExecutionRoleDefaultPolicy0DBB737A": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "secretsmanager:GetSecretValue",
"Effect": "Allow",
"Resource": {
"Ref": "SecretA720EF05"
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "TaskDefExecutionRoleDefaultPolicy0DBB737A",
"Roles": [
{
"Ref": "TaskDefExecutionRoleB4775C97"
}
]
}
}
}
}
27 changes: 27 additions & 0 deletions packages/@aws-cdk/aws-ecs/test/fargate/integ.secret-json-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import * as cdk from '@aws-cdk/core';
import * as ecs from '../../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-ecs-integ-secret-json-key');

const secret = new secretsmanager.Secret(stack, 'Secret', {
generateSecretString: {
generateStringKey: 'password',
secretStringTemplate: JSON.stringify({ username: 'user' })
}
});

const taskDefinition = new ecs.FargateTaskDefinition(stack, 'TaskDef', {
memoryLimitMiB: 1024,
cpu: 512
});

taskDefinition.addContainer('web', {
image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
secrets: {
PASSWORD: ecs.Secret.fromSecretsManager(secret, 'password')
}
});

app.synth();
44 changes: 44 additions & 0 deletions packages/@aws-cdk/aws-ecs/test/test.container-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,50 @@ export = {

},

'use a specific secret JSON key as environment variable'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'TaskDef');

const secret = new secretsmanager.Secret(stack, 'Secret');

// WHEN
taskDefinition.addContainer('cont', {
image: ecs.ContainerImage.fromRegistry('test'),
memoryLimitMiB: 1024,
secrets: {
SECRET_KEY: ecs.Secret.fromSecretsManager(secret, 'specificKey'),
}
});

// THEN
expect(stack).to(haveResourceLike('AWS::ECS::TaskDefinition', {
ContainerDefinitions: [
{
Secrets: [
{
Name: 'SECRET_KEY',
ValueFrom: {
'Fn::Join': [
'',
[
{
Ref: 'SecretA720EF05'
},
':specificKey::'
]
]
}
},
]
}
]
}));

test.done();

},

'can add AWS logging to container definition'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
Expand Down