(aws-ecs): FargateService adds In- and EgressRules for all SecurityGroups
See original GitHub issueWhat is the problem?
When configuring a FargateService with multiple SecurityGroups additional Egress Rule changes (e.g. for Load Balancer to Target) are created for all of them. This applies even for external SGs that are imported by fromSecurityGroupId()
and have set {mutable: false}
.
Reproduction Steps
I created a minimal example in this github repository
const externalDbSg = SecurityGroup.fromSecurityGroupId(
this,
"ExternalDbSg",
Fn.importValue("external-database-sg"),
{ mutable: false, allowAllOutbound: true }
);
const fargateSG = new SecurityGroup(this, "FargateSg", {
vpc,
});
const targetGroup = new ApplicationTargetGroup(this, "TargetGroup", {
vpc,
port: 8080,
});
new ApplicationLoadBalancer(this, "Alb", {
vpc,
internetFacing: true,
}).addListener("Listener", {
port: 443,
certificates: [ListenerCertificate.fromArn("arn")],
defaultAction: ListenerAction.forward([targetGroup]),
});
const task = new TaskDefinition(this, "Task", {
compatibility: Compatibility.FARGATE,
cpu: "512",
memoryMiB: "1024",
});
task.addContainer("Image", {
image: ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
portMappings: [{ containerPort: 8080 }],
});
const service = new FargateService(this, "FargateService", {
cluster: cluster,
taskDefinition: task,
securityGroups: [fargateSG, externalDbSg],
});
service.attachToApplicationTargetGroup(targetGroup);
What did you expect to happen?
The Rules are only created for the SG I created for the FargateService (and is mutable).
I’m migrating the service from Cloudformation to CDK and before there was no issue attaching multiple SGs a FargateService. I understand that now where the L2 Construct is creating the Rule for Traffic from the LoadBalancer itself and has no real way of “knowing which SG belongs to the service”. But there should be a way (that I might be missing) of implementing this so that not every Egress rule is created multiple times.
What actually happened?
For every SG assigned to the FargateService Egress rules are created for the Resources that have a connection to the service. In my provided example this is only the Load Balancer but this applies for all connections added to the service. While a single additional Egress rule is not that much of an issue, this can become quite irritating when working with multiple services that have access to multiple Resources.
– EDIT –
I made some pictures to make the situation clear
- ExternalSg imported with
mutable: true
- ExternalSg imported with
mutable:false
- Desired Outcome
CDK CLI Version
2.1.0
Framework Version
2.1.0
Node.js Version
14.17.3
OS
Ubuntu 20.04
Language
Typescript
Language Version
3.9.7
Other information
No response
Issue Analytics
- State:
- Created 2 years ago
- Reactions:3
- Comments:11 (1 by maintainers)
Top GitHub Comments
Thanks for opening this issue and your detailed descriptions, @bedaka. It looks like there is a bug here, and also an opportunity to make security group management better for ecs services. I am not sure right away what is the right direction here. I will need to dive deeper and come back to it.
@stoicad thank you for your help so far. I was able to follow your suggestion and in fact creating a loadBalancer SG explicitly and adding
allowAllOutbound: true
solved the creation of the Egress Groups in question to the LB.@madeline-k (sorry for pinging directly) HOWEVER this workaround does not solve the underlying issue, that I tried to point at. I updated my minimal example to show the issue with a little bit more complex setup. Please imagine the following:
service.connection.allowTo(testSG, Port.tcp(1234), "Fargate to Test)
This will results in the following rule being created which is not expected/wanted:
It seems like this is possible because the IngressRule is not attached to the externalSg and it is merely used as the SourceSecurityGroup. It seems like there is an attribute next to
mutable
missing (for exampleexternal: false
) which allows to disable the usage of an imported group as a SourceSecurityGroup.I updated my example accordingly.