AWS CloudFormation模板:是否可以将许多CidrIp添加为列表?

时间:2016-04-20 09:17:06

标签: amazon-cloudformation

我想在云形成模板中创建安全组的入站规则。我想从许多不同的IP打开3306端口。

    "SecurityGroupIngress": [
            {
                "IpProtocol": "tcp",
                "CidrIp": "0.0.0.0/0",
                "FromPort": "3306",
                "ToPort": "3306"
            }

我知道文档将String称为CidrIp类型但是可以执行类似["100.10.77.66/32", "100.10.66.66/32" , "101.10.77.66/32"]之类的操作以避免多次写同一个块吗?

4 个答案:

答案 0 :(得分:7)

不幸的是,CloudFormation Intrinsic Functions没有可用的迭代,并且正如您所指出的那样,AWS::EC2::SecurityGroupIngress资源本身只接受StringCidrIp {1}}属性。

作为替代方案,我建议选择一种中间格式,使用预处理器编译为CloudFormation模板JSON,如果/需要更强的表现力。您可以使用像troposphere这样的功能齐全的库,但它也很容易编写您自己的基本预处理层,以满足您的用例和编程语言/库首选项。

我目前的选择是YAML与嵌入式Ruby(ERB)的组合,主要是因为我已经熟悉它们。这是一个示例template.yml.erb文件,它将生成上面的示例JSON:

SecurityGroupIngress:
<% ["100.10.77.66/32", "100.10.66.66/32" , "101.10.77.66/32"].each do |cidr| -%>
- IpProtocol: tcp
  CidrIp: <%=cidr%>
  FromPort: 3306
  ToPort: 3306
<% end -%>

这是一个最小的预处理脚本process_template.rb

require 'erb'
require 'yaml'
require 'json'
puts JSON.pretty_generate(YAML.load(ERB.new(ARGF.read, nil, '-').result))

运行ruby ./process_template.rb template.yml.erb会产生:

{
  "SecurityGroupIngress": [
    {
      "IpProtocol": "tcp",
      "CidrIp": "100.10.77.66/32",
      "FromPort": 3306,
      "ToPort": 3306
    },
    {
      "IpProtocol": "tcp",
      "CidrIp": "100.10.66.66/32",
      "FromPort": 3306,
      "ToPort": 3306
    },
    {
      "IpProtocol": "tcp",
      "CidrIp": "101.10.77.66/32",
      "FromPort": 3306,
      "ToPort": 3306
    }
  ]
}

答案 1 :(得分:6)

不要害怕,因为文档声明它只接受String而不是List,因此需要多个块。

与在Web控制台中创建入口规则的方式相同,每个CIDR都有一条新规则。

答案 2 :(得分:0)

根据wjordan的方法,您可以通过类似的方式在ERB模板的分隔文件中指定CidrIp。首先,创建一个ERB文件。例如,让我们看一下sgi-trusted-ip-range.erb

Type: "AWS::EC2::SecurityGroupIngress"
<%- Dir.glob("trusted-ip-range/cidr-*.csv").map {|f| File.readlines(f)}.flatten.map(&:strip).each do |cidr| -%>
- IpProtocol: tcp
  CidrIp: <%=cidr%>
  FromPort: 80
  ToPort: 80
- IpProtocol: tcp
  CidrIp: <%=cidr%>
  FromPort: 443
  ToPort: 443
<%- end -%>

根据您的要求符合CIDR列表文件,遵循命名约定trusted-ip-range/cidr-*.csv,其中内容为:

100.10.77.66/32
100.10.66.66/32
101.10.77.66/32

然后,通过这个单行生成YAML文件:

ruby -r erb -e 'ERB.new(ARGF.read, nil, "-").run'

此外,您可以验证生成的YAML文件,如下所示:

aws cloudformation validate-template --template-body "file://__PATH_TO_FILE__.yml"

答案 3 :(得分:0)

我很好奇为什么没有关于Cloudformation Custom资源的答案。 您仍然可以使用lambda函数创建自己的自定义安全组,该函数根据您的cloudformation状态(创建,更新,删除)创建/删除安全组。 我编写了一个简单的自定义资源here,请在方便时随意修改自定义资源参数。 然后,您可以在创建堆栈时输入逗号分隔的cidr块。 您可以使用以下方法在实例(或其他资源)上引用此安全组:
!GetAtt CustomSG.SecGroupId