'How to add a security group to an existing RDS with CDK without cyclic-dependency

I have a multi-stack application where I want to deploy an RDS in one stack and then in a later stack deploy a Fargate cluster that connects to the RDS.

Here is how the rds gets defined:

    this.rdsSG = new ec2.SecurityGroup(this, `ecsSG`, {
      vpc: props.vpc,
      allowAllOutbound: true,
    });

    this.rdsSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(5432), 'Ingress 5432');

    this.aurora = new rds.ServerlessCluster(this, `rds`, {
      engine: rds.DatabaseClusterEngine.AURORA_POSTGRESQL,
      parameterGroup: rds.ParameterGroup.fromParameterGroupName(this, 'ParameterGroup', 'default.aurora-postgresql10'),
      vpc: props.vpc,
      securityGroups: [this.rdsSG],
      // more properties below
    });

With that add ingress rule everything is fine, since both the RDS and Fargate are in the same VPC, I can communicate fine. It worries me making that open the world even though its in its own VPC.

    const ecsSG = new ec2.SecurityGroup(this, `ecsSG`, {
      vpc: props.vpc,
      allowAllOutbound: true,
    });

    const service = new ecs.FargateService(this, `service`, {
      cluster,
      desiredCount: 1,
      taskDefinition,
      securityGroups: [ecsSG],
      assignPublicIp: true,
    });

How can I remove the ingress rule and allow inbound connections to the RDS from that ecsSG since it gets deployed later? If I try to call the following command from the deploy stack, I get a cyclic dependency error:

    props.rdsSG.connections.allowFrom(ecsSG, ec2.Port.allTcp(), 'Aurora RDS');

Thanks for your help!



Solution 1:[1]

This turned out to be easier than I thought- you can just flip the connection so that rather than trying to modify the rds to accept a security group of the ecs, you use the allowTo to establish a connection to the rds instance.

    ecsSG.connections.allowTo(props.rds, ec2.Port.tcp(5432), 'RDS Instance');

Solution 2:[2]

Also maybe the other way round the RDS security group might be better described by aws_rds module rather than aws_ec2 module https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_rds/CfnDBSecurityGroup.html (couldn't post a comment due to low rep)

Solution 3:[3]

Just as an additional possibility here. What works for me is that I don't need to define any security group. Just the service and the db, and connect the two:

const service = new ecsPatterns.ApplicationLoadBalancedEc2Service(
    this,
    'app-service',
    {
        cluster,
        ...
    },
);
      
const dbCluster = new ServerlessCluster(this, 'DbCluster', {
    engine: dbEngine,
    ...
});
dbCluster.connections.allowDefaultPortFrom(service.service);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Coherent
Solution 2 Dhruv
Solution 3 webjunkie