24

I have a cfn stack that (among other things), creates a VPC, several security groups, and a handful of EC2 instances. It's trivial to assign security groups that are created within the stack to instances that are also created by the stack. However, I'm interested in the default VPC SG.

When a VPC gets created (whether manually though the GUI, by cloudformation, or any other means), AWS creates a default security group with an "allow all" rule for any instance in that group.

What I am trying to do is assign this default security group along with several other SGs to instances created by the stack. This is proving to be far more difficult than I anticipated. Here are some snippets showing what I have going on:

"AllowSSHSecGroup":{
      "Type":"AWS::EC2::SecurityGroup",
      "Properties":{
        "GroupDescription":"Allow SSH from anywhere",
        "VpcId":{
          "Ref":"DevVPC"
        },
        "SecurityGroupIngress":[
          {
            "IpProtocol":"tcp",
            "FromPort":"22",
            "ToPort":"22",
            "CidrIp":"0.0.0.0/0"
          }
        ]
      }
},
"Instance001" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "ImageId" : "ami-7eab224e",
        "InstanceType" : "m1.large",
        "AvailabilityZone" : "us-west-2a",
        "PrivateIpAddress" : "10.22.0.110",
        "SecurityGroupIds" : [ {"Ref" : "AllowSSHSecGroup"} ],
        "SubnetId" : { "Ref" : "PublicSubnet" },
        "KeyName" : "erik-key",
        "DisableApiTermination" : "false",
        "Tags" : [ { "Key": "Name", "Value": "Instance001"} ]
      }
}

In the above snippet, I'm creating an "allow ssh" security group and assigning that to an instance. As mentioned, my stack also creates a VPC (which this instance is launched in), which in turn creates a default security group. Unfortunately, since this group is created automatically by AWS, its group ID is unavailable to the stack, making it impossible to reference by ID. I initially thought that the SecurityGroups property would be an option, as that would allow me to reference the default SG by its name, default. That doesn't work, though, as the SecurityGroups property is only for EC2 Security Groups, not VPC Security Groups.

So I'm stuck. I have opened up a case with AWS support on this, but so far, they've not been helpful. Any ideas on how I can accomplish this?

Ikar Pohorský
  • 305
  • 3
  • 5
EEAA
  • 108,414
  • 18
  • 172
  • 242

3 Answers3

25

Referencing the default security group is possible using:

{ "Fn::GetAtt" : ["VPC", "DefaultSecurityGroup"] }

Where "VPC" is your VPC resource name.

With AWS::EC2::SecurityGroupIngress and AWS::EC2::SecurityGroupEgress, you can augment the permissions of this default security group.

I think this is what you want:

"VPCDefaultSecurityGroupIngress": {
  "Type" : "AWS::EC2::SecurityGroupIngress",
  "Properties" : {
    "GroupId": { "Fn::GetAtt" : ["VPC", "DefaultSecurityGroup"] },
    "IpProtocol":"tcp",
    "FromPort":"22",
    "ToPort":"22",
    "CidrIp":"0.0.0.0/0"
  }
},

As mentioned by @artbristol and @gabriel, this allows Ingress/Egress rules to be added to the default security group for the VPC in a single stack deployment.

I'm pretty sure that the self-referential problem still impacts any attempts at changing any of the other properties on the default security group of the VPC. A good example of this would be adding Tags, or a Description. If you wish to change these things, you'll have to deal with extraneous security groups laying around.

IanBlenke
  • 351
  • 3
  • 3
10

Well, as it turns out, AWS support replied and informed me that they recognize that this is a feature gap in CloudFormation, and it has been submitted to the development team as a feature request.

So until this feature is implemented, the workaround is to create your own "default" security group that replicates the same behavior as the "real" default SG. Unfortunately, due to the self-referential aspect of this setup, it is still not possible to do within one single stack deployment. The alternative is to deploy the stack once, without assigning the default security group your instances. Then once the stack is created (and you've had a chance to see what the Security Group ID for default is), you can add that SG ID to your instances.

EEAA
  • 108,414
  • 18
  • 172
  • 242
  • 2
    I believe if you follow this https://forums.aws.amazon.com/thread.jspa?messageID=466960 and create a `SecurityGroupIngress`, referring to your synthetic default security group, you can get the self-reference that you want, within a single stack deployment – artbristol Oct 22 '13 at 08:33
  • This is correct. For example, if you run the CloudFormer stack on an existing VPC containing default, self-referential security groups, it will generate a template where the SecurityGroupIngress is broken out as its own resource with both `GroupId` and `SourceSecurityGroupId` set to `{ "Ref": "" }` – Gabriel Dec 12 '13 at 22:18
  • 2
    Do you happen to know if this has been updated? Having to duplicate the default security group is annoying. – Paul MacDougall Sep 09 '14 at 19:21
  • 1
    FWIW: "Remove Default Rule" https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html – Jakub M. Aug 21 '18 at 09:07
0

As of writing December 2020 update/expansion,

To expand a bit on this answer

For some reference material, getting the default security group you can now use get attribute as referenced here on AWS Cloudformation VPC docs

I personally, work with yaml, so if this helps anyone else wondering how to reference a VPC's default security group in yaml, this is how:

!GetAtt VPC.DefaultSecurityGroup

Also shown with an example in yaml format taken from this answer to see it in context:

myELBIngressGroup:
  Type: AWS::EC2::SecurityGroup
  Properties:
    GroupDescription: ELB ingress group
    SecurityGroupIngress:
      - IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        GroupId: !GetAtt VPC.DefaultSecurityGroup
        CidrIp: "0.0.0.0/0"