Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I assign a created SecurityGroup to an ELB from CloudFormation?

I've got a CloudFormation script that generates a SecurityGroup and an ELB; I'm trying to reference the SecurityGroup in the ELB creation; here's the resources bit:

    "ELBSecurityGroup" : {
        "Type" : "AWS::EC2::SecurityGroup",
        "Properties" : {
            "GroupDescription" : "Security group for the Arena dev stack",
            "SecurityGroupIngress" : [
                {"IpProtocol" : "tcp", "FromPort" : 80, "ToPort" : 80, "CidrIp" : { "Ref" : "OfficeIp" }}
            ]
        }
    },

    "ProjectLoadBalancerTest" : {
        "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
        "Properties" : {
            "AvailabilityZones" : { "Fn::GetAZs" : "" },
            "Instances" : [  ],
            "Listeners" : [ {
                "LoadBalancerPort" : "80",
                "InstancePort" : "12345",
                "Protocol" : "HTTP"
            } ],
            "HealthCheck" : {
                "Target" : {
                    "Fn::Join" : [ "", [ "HTTP:", "12345", "/status.json" ] ]
                },
                "HealthyThreshold" : "2",
                "UnhealthyThreshold" : "5",
                "Interval" : "60",
                "Timeout" : "30"
            },
            "SecurityGroups" : [
                { "Ref" : "ELBSecurityGroup" }
            ]
        }
    }

Unfortunately, this fails with:

Invalid id: "sebelbtest2-ELBSecurityGroup-1F5Z5DIIVQKD1" (expecting "sg-...")

So how can I reference ELBSecurityGroup for use as a property in the ELB creation?

Thanks!

like image 512
Seb Avatar asked Jan 14 '14 08:01

Seb


2 Answers

As mytwocents mentioned, the solution is to use Fn::GetAtt. SecurityGroups are now supported by this function: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html

This works on the ELB:

...
"SecurityGroups" : [
    { "Fn::GetAtt" : [ "ELBSecurityGroup", "GroupId" ] }
]
...

Note. If you're putting this into a non-default VPC you'll also need to specify the VPC for the security group, and a subnet ID for the ELB.

like image 66
sorohan Avatar answered Sep 18 '22 15:09

sorohan


As my CloudFormation script is all done within a VPC, I figured out what the problem was - I was creating the Security group, but not specifying the VpcId for it.

Security groups appear to be either normal security groups, or VPC security groups; if you do { "Ref": "MySecurityGroup" } on a normal one, you get the security group name, but not the ID. If you do { "Ref": "MySecurityGroup" } on a VPC one, you get back the sg-abcdef id, which is what is required for the ELB security group parameter.

So the full answer is:

"ELBSecurityGroup" : {
    "Type" : "AWS::EC2::SecurityGroup",
    "Properties" : {
        "GroupDescription" : "Security group for the ELB",
        "VpcId" : { "Ref" : "VpcId" },
        "SecurityGroupIngress" : [
            {"IpProtocol" : "tcp", "FromPort" : 80, "ToPort" : 80, "CidrIp" : { "Ref" : "OfficeIp" }}
        ]
    }
},
"MyELB": {
    "Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
    "Properties" : {
        "AvailabilityZones" : { "Fn::GetAZs" : "" },
        "Listeners" : [ {
            "LoadBalancerPort" : "80",
            "InstancePort" : 8000,
            "Protocol" : "HTTP"
        } ],
        "SecurityGroups" : [ { "Ref" : "ELBSecurityGroup" } ]
    }
}

This all works perfectly (provided everything you're doing is within your VPC) and in my configuration, will successfully limit access to whatever OfficeIP is set to.

like image 40
Seb Avatar answered Sep 19 '22 15:09

Seb