如何从CloudFormation将创建的SecurityGroup分配给ELB?

时间:2014-01-14 08:14:05

标签: amazon-web-services amazon-elb amazon-cloudformation

我有一个生成SecurityGroup和ELB的CloudFormation脚本;我正在尝试在ELB创建中引用SecurityGroup;这是资源位:

    "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" }
            ]
        }
    }

不幸的是,这失败了:

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

那么如何引用ELBSecurityGroup作为ELB创建中的属性?

谢谢!

5 个答案:

答案 0 :(得分:11)

正如mytwocents所说,解决方案是使用Fn :: GetAtt。此功能现在支持SecurityGroup:http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html

这适用于ELB:

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

请注意。如果您将其置于非默认VPC中,则还需要为安全组指定VPC,并为ELB指定子网ID。

答案 1 :(得分:7)

由于我的CloudFormation脚本都是在VPC中完成的,我想出了问题所在 - 我正在创建安全组,但没有为它指定VpcId。

安全组似乎是普通安全组或VPC安全组;如果您在正常情况下执行{ "Ref": "MySecurityGroup" },则会获得安全组名称,但不会获取ID。如果您在VPC上执行{ "Ref": "MySecurityGroup" },则会返回sg-abcdef ID,这是ELB安全组参数所需的内容。

完整的答案是:

"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" } ]
    }
}

这一切都完美无缺(如果您所做的一切都在您的VPC中),并且在我的配置中,将成功限制对OfficeIP设置的访问权限。

答案 2 :(得分:1)

嗯...

好像模板正在返回安全组的名称而不是其ID。

根据the documentationSecurityGroups似乎只能附加到VPC中的负载均衡器。

如果是我,我会做两件事之一(或两件事):

  • 将我的问题发布到official AWS CloudFormation forum,尝试从该团队的某个人那里得到答案。
  • 使用AWS控制台,SDK或CLI工具以您希望的方式设置您的环境,然后使用CloudFormer工具生成与您的环境相匹配的CloudFormation模板。

答案 3 :(得分:0)

我遇到了同样的问题 - 但我认为,由于这只是初始设置,弹性负载均衡器可以从云形成中单独管理,直到它们解决了这个问题。此外,云端实例并不完全可靠,尤其是当您有安全组引用其他安全组时。

我希望GetAttr函数调用ID可以正常工作,但安全组不在GetAttr支持的列表中: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html

答案 4 :(得分:0)

试试这个安全组:

"ELBSecurityGroup" : {
    "Type" : "AWS::EC2::SecurityGroup",
    "Properties" : {
        "GroupDescription" : "Security group for the Arena dev stack",
        "SecurityGroupIngress" : [ {
            "IpProtocol" : "tcp",
            "FromPort" : 80,
            "ToPort" : 80,
            "SourceSecurityGroupOwnerId" : { "Fn::GetAtt" : [ "ProjectLoadBalancerTest", "SourceSecurityGroup.OwnerAlias" ] },
            "SourceSecurityGroupName" : { "Fn::GetAtt" : [ "ProjectLoadBalancerTest", "SourceSecurityGroup.GroupName" ] }
        } ]
    }
},

并从ELB定义中删除"SecurityGroups"。这将允许从您的ELB到您的应用服务器的流量。

看起来您还希望将ELB流量限制在您的办公室IP上。用apache指令这样做会更好。