Как назначить созданную SecurityGroup для ELB из CloudFormation?

У меня есть CloudFormation script, который генерирует SecurityGroup и ELB; Я пытаюсь ссылаться на SecurityGroup в создании ELB; здесь бит ресурсов:

    "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?

Спасибо!

Ответ 1

Поскольку моя CloudFormation script выполняется в VPC, я выяснил, в чем проблема: я создавал группу безопасности, но не указывал VpcId для нее.

Группы безопасности представляют собой либо обычные группы безопасности, либо группы безопасности VPC; если вы выполняете { "Ref": "MySecurityGroup" } на обычном, вы получаете имя группы безопасности, но не идентификатор. Если вы выполняете { "Ref": "MySecurityGroup" } на VPC, вы возвращаете идентификатор sg-abcdef, что и требуется для параметра группы безопасности 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

Как упоминалось выше, решение заключается в использовании Fn:: GetAtt. SecurityGroups теперь поддерживаются этой функцией: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html

Это работает на ELB:

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

Примечание. Если вы помещаете это в не-по умолчанию VPC, вам также необходимо указать VPC для группы безопасности и идентификатор подсети для ELB.

Ответ 3

Хммм...

Кажется, что шаблон возвращает имя группы безопасности вместо идентификатора.

Основываясь на документации, похоже, что SecurityGroups можно подключить только к балансировщику нагрузки в VPC.

Если бы это был я, я бы сделал одну из двух вещей (или обоих):

Ответ 4

У меня была та же проблема, но я решил, что, поскольку это только для первоначальной настройки, балансировщик эластичной нагрузки можно управлять отдельно от облачного образования, пока они не будут работать с этой ошибкой. Кроме того, облако прежнего не является полностью надежным, особенно когда у вас есть группы безопасности, ссылающиеся на другие группы безопасности.

Я надеялся, что вызов функции GetAttr для ID будет работать, но группы безопасности не находятся в поддерживаемом списке GetAttr: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html

Ответ 5

Попробуйте это для вашей SecurityGroup:

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

и удалите "SecurityGroups" из вашего определения ELB. Это позволит трафик с вашего ELB на серверы приложений.

Похоже, вы также хотите ограничить трафик ELB на IP-адрес вашего офиса. Это было бы лучше сделать с чем-то вроде директив apache.