Search code examples
amazon-web-servicesamazon-ec2aws-cloudformationaws-security-group

CloudFormation SecurityGroup Circular Reference


I am working with two simple web apps that need to talk to each other. Within AWS CloudFormation I have a template that creates an EC2 instance and installs both applications on the same server (eventually I'll split them up, but for now they live on the same EC2 instance).

As part of the EC2 instance, I have to define the SecurityGroup to use. For now I have been using a default one, but I would like to build one dynamically. In the group I allow SSH in from my machine, and a few ports from the box to itself.

When using the default group, after the fact I can add in the server's public ip to its own security group to allow it to communicate to itself. The problem is during the CloudFormation template, I am getting a circular reference between the SecurityGroup and the EC2 instance. The instance needs a SecurityGroup to start, and that group needs to contain the Public IP rule for the EC2 box.

Is there a better way to do this, or somehow lock in something along the lines of "localhost" to allow these traffic in for now?


Solution

  • You have a couple of options:

    1. You can have a self referencing security group for this, which will mean the EC2 instance will be allowed to communicate to itself since is on that security group. There is a caveat, and that is don't use embedded ingress and egress rules in the AWS::EC2::SecurityGroup, instead use AWS::EC2::SecurityGroupEgress and AWS::EC2::SecurityGroupIngress separate, as noted here.

    Would look like:

    "Resources" : {
        "SelfRefSecurityGroup" : {
          "Type" : "AWS::EC2::SecurityGroup",
          "Properties" : {
            "GroupDescription" : "Has access to itself",
            "VpcId" : "vpc-xxxxxx"
          }
        },
        "MySecurityGroupIngress" : {
             "Type" : "AWS::EC2::SecurityGroupIngress",
             "Properties" : {
                 "GroupId" : { "Ref" : "SelfRefSecurityGroup" },
                 "IpProtocol" : "tcp",
                 "ToPort" : "65535",
                 "FromPort" : "0",
                 "SourceSecurityGroupId" : { "Ref" : "SelfRefSecurityGroup" }
             },
             "DependsOn" : "SelfRefSecurityGroup"
         }
    
    1. Best option: Create 2 host entries in the box (or better yet set the dns entries using a Route53 private hosted zone):

      webapp1.com 127.0.0.1

      webapp2.com 127.0.0.1

    I wouldn't advice having the box talk to itself via its public IP. Probably you'll even incur in cost! (https://aws.amazon.com/ec2/pricing/on-demand/) Plus the added maintenance of the SG.