aws / aws/aws-cdk

addSecurityGroup didn't work for ECS_pattern ALB Fargate

Open
#5,635 15 comments 12 reactions 0 assignees View on GitHub
@aws-cdk/aws-ecs-patterns bug effort/medium p2
Dominant language
TypeScript
Stars
12.9k
Forks
4.6k
Avg merge
2d 3h
Merged PRs (30d)
83

Description

I was not able to add another security group to the ECS Pattern for ALB Fargate service using Fargate.cluster.connections.addSecurityGroup() method.

### Reproduction Steps

ecs-fargate.ts
```
export class ECSFargateStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// Imports the VPC from the name provided
const vpc = ec2.Vpc.fromLookup(this, this.stackName+'VPC', {
vpcName: vpc_name
})

const laravelAppSecret = new secrets.Secret(this, this.stackName+'_LaravelAppKeySecret',{
secretName: this.stackName+'-LaravelAppKey',
generateSecretString: {
includeSpace: false,
passwordLength: 32,
excludeCharacters: '"@/\\'
}
})

// Builds and publishes the container image
const image = new ecr_assets.DockerImageAsset(this, this.stackName+'_Image', {
directory: __dirname+'/../docker/'+applicationName,
buildArgs:{
'tag':applicationName
}
})

//Creates the ECS Fargate cluster, task, and application load balancer
const fargateservice = new ecs_patterns.ApplicationLoadBalancedFargateService(this, this.stackName, {
vpc: vpc,
publicLoadBalancer: publicLoadBalancer,
desiredCount: desiredCount,
taskImageOptions: {
image: ecs.ContainerImage.fromEcrRepository(image.repository),
enableLogging: true,
logDriver: new ecs.AwsLogDriver({ streamPrefix: this.stackName+'-'+this.region }),
environment:{
'APP_DEBUG': 'false',
'DB_USERNAME': cdk.Fn.importValue('DBUser'),
'DB_DATABASE': cdk.Fn.importValue('DBName'),
'DB_HOST': cdk.Fn.importValue('DBHost'),
'DB_PORT': '3306'
},
secrets: {
'DB_PASSWORD': ecs.Secret.fromSecretsManager(secrets.Secret.fromSecretArn(this, this.stackName+'_DBPasswordSecret', cdk.Fn.importValue('DBSecretArn'))),
'APP_KEY': ecs.Secret.fromSecretsManager(laravelAppSecret)
},
containerPort: 80,
containerName: this.stackName,
},
cpu: cpu,
memoryLimitMiB: memoryLimit
})

fargateservice.cluster.connections.addSecurityGroup(ec2.SecurityGroup.fromSecurityGroupId(this, this.stackName+'_DBSecurityGroup', cdk.Fn.importValue('DBSecurityGroupId')))
}
}
```

db.ts
```
export class RDSStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// Imports the VPC from the name provided
const vpc = ec2.Vpc.fromLookup(this, this.stackName+'VPC', {
vpcName: vpc_name
})

//Creates secrets needed for the stack
const dbSecret = new secrets.Secret(this, this.stackName+'_DBPasswordSecret',{
secretName: this.stackName+'-DBPassword',
generateSecretString: {
includeSpace: false,
passwordLength: 32,
excludeCharacters: '"@/\\'
}
})

//Creates Security Group and adds Ingress rule to open 3306 to everyone
const sg = new ec2.SecurityGroup(this, this.stackName+'_SecurityGroup', {
securityGroupName: this.stackName+'_SecurityGroup',
vpc: vpc,
allowAllOutbound: allOutbound,
description: 'Security Group to access '+this.stackName+' database'
})
sg.connections.allowInternally(ec2.Port.tcp(3306))

const dbSubnetGroup = new rds.CfnDBSubnetGroup(this, this.stackName+'_DBSubnetGroup',{
subnetIds: vpc.privateSubnets.map(subnet => subnet.subnetId),
dbSubnetGroupDescription: 'Aurora Subnet Group'
})
const db = new rds.CfnDBCluster(this, this.stackName+'-AuroraRDSCluster', {
engine: 'aurora',
engineMode: 'serverless',
engineVersion: '5.6',
masterUsername: dbUsername,
masterUserPassword: dbSecret.secretValue.toString(),
dbSubnetGroupName: dbSubnetGroup.ref,
availabilityZones: vpc.availabilityZones,
databaseName: dbName,
deletionProtection: dbdelectionprotection,
backupRetentionPeriod: 30,
scalingConfiguration:{
minCapacity: dbMin,
maxCapacity: dbMax,
autoPause: dbAutoPause,
secondsUntilAutoPause: dbAutoPauseSeconds
},
vpcSecurityGroupIds: [sg.securityGroupId],
})

//Creates Outputs that can be used by other templates in the same account
new cdk.CfnOutput(this, this.stackName+'DBUser', {
value: db.masterUsername as string,
exportName: 'DBUser'
})
new cdk.CfnOutput(this, this.stackName+'DBName', {
value: db.databaseName as string,
exportName: 'DBName'
})
new cdk.CfnOutput(this, this.stackName+'DBHost', {
value: db.attrEndpointAddress,
exportName: 'DBHost'
})
new cdk.CfnOutput(this, this.stackName+'DBPort', {
value: db.attrEndpointPort,
exportName: 'DBPort'
})
new cdk.CfnOutput(this, this.stackName+'DBSecretArn',{
value: dbSecret.secretArn,
exportName: 'DBSecretArn'
})
new cdk.CfnOutput(this, this.stackName+'DBSecurityGroupId',{
value: sg.securityGroupId,
exportName: 'DBSecurityGroupId'
})
}
}
```

### Error Log

No real error messages just don't see the security group in the cloud formation json nor will the application connect to the database.

### Environment

- **CLI Version : 1.19
- **Framework Version: 1.19
- **OS : Mac OSX
- **Language : typescript

### Other

I am currently using this as a workaround as it has a similar effect:

ec2.SecurityGroup.fromSecurityGroupId(this, this.stackName+'_DBSecurityGroup', cdk.Fn.importValue('DBSecurityGroupId')).connections.allowFrom(fargateservice.service.connections, ec2.Port.tcp(3306))

---

This is :bug: Bug Report

Contributor guide

Open the contributing guide

Research direction

Start with the ECSFargateStack in ecs-fargate.ts and the security group definition in db.ts. Synthesize the stacks and inspect the generated CloudFormation to trace whether fargateservice.cluster.connections.addSecurityGroup() affects the Fargate service. Done means the imported database security group is represented in the template and the application can connect to the database without relying on the workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, typescript
Domain
cloud, networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.