【问题标题】:AWS CloudFormation template: Is it possible to add many CidrIp as a list?AWS CloudFormation 模板:是否可以将许多 CidrIp 添加为列表?
【发布时间】:2016-08-12 20:33:37
【问题描述】:

我想在云形成模板中创建安全组的入站规则。我想从许多不同的 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"] 的操作以避免多次写入同一个块?

【问题讨论】:

    标签: amazon-cloudformation


    【解决方案1】:

    基于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 -%>
    

    按照命名约定trusted-ip-range/cidr-*.csv 放置满足您的要求的 CIDR 列表文件,例如内容所在的位置:

    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' sgi-trusted-ip-range.erb
    

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        不幸的是,CloudFormation 的Intrinsic Functions 没有可用的迭代,正如您所指出的,AWS::EC2::SecurityGroupIngress 资源本身只接受单个StringCidrIp 属性。

        作为替代方案,如果/当需要更大的表达能力时,我建议选择一种中间格式,以使用预处理器编译成 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
            }
          ]
        }
        

        【讨论】:

          【解决方案4】:

          不要害怕,因为文档指出它只接受字符串而不接受列表,因此需要多个块。

          将其视为在 Web 控制台中创建入口规则的方式相同,每个 CIDR 一个新规则。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-08-26
            • 2018-09-06
            • 2019-01-20
            • 2014-10-06
            • 2023-03-19
            • 1970-01-01
            • 2019-11-14
            • 1970-01-01
            相关资源
            最近更新 更多