使用 Cloudformation 和 Pystache 派生 IP 范围和网络掩码

问题描述

所以,我有一个有趣的例子 - Cloudformation 允许使用 Mustache 模板(通过 Pystache)通过 AWS::CloudFormation::Init 构建配置文件(他们把这个埋了几段,但它就在那里)。>

这对我很有用,因为我需要写出一些网络详细信息来为 OpenVPN 服务器创建配置文件。到目前为止,一切都很好。

但这就是它变得棘手的地方 - AWS 喜欢 CIDR 表示法(我需要对 AWS 资源和此使用相同的参数)。但是 OpenVPN 喜欢使用旧的 IP 范围和网络掩码格式。我目前正在尝试找到一种转换它的好方法。我可以使用 CloudFormation 函数,也可以尝试找到在 Mustache 中进行转换的方法

我可以使用 Fn::Select 和 Fn::Split 的组合来获取 IP 范围以拉取 CIDR 的前半部分,但目前获取网络掩码让我感到困惑。

到目前为止的示例

          "/etc/openvpn/server/configname.conf" : {
            "source" : {"Fn::Sub" : 
               [ "https://${ConfigBucket}.s3.amazonaws.com/Path/To/configname.conf.mustache",{ "ConfigBucket" : { "Fn::ImportValue" : "ConfigBucket-Export-Name" }} ]
            },"context" : {
              "VpnCIDR" : { "Ref" : "VpnCIDRRange"},"VpnIPRange" : { "Fn::Select" : [ "0",{"Fn::Split" : ["/",{ "Ref" : "VpnCIDRRange"}]}]},"AwsCIDR" : { "Fn::ImportValue" : { "Fn::Sub" : "${VPCName}-VPC-CIDR" } },"AwsIPRange" : { "Fn::Select" : [ "0",{ "Fn::ImportValue" : { "Fn::Sub" : "${VPCName}-VPC-CIDR" }}]}]}
            }
          } 

解决方法

好的,所以我最终使用一个简单的 CloudFormation 宏解决了这个问题,该宏接受一个 CIDR 范围并返回一个包含 CIDR、子网和网络掩码的 JSON 对象 - 例如,给定 192.168.1.0/24,它将返回以下 JSON用于包含在 CloudFormation 模板中的片段

{
  'CIDR' : '192.168.1.0/24','subnet' : '192.168.1.0','netmask' : '255.255.255.0'
}

有问题的代码发布到这个要点:https://gist.github.com/AdamLuchjenbroers/3165ab18bb0ee9da95ad6bf514f415e0

它也可以使用堆栈导出的名称(这是必需的,因为显然 Fn::ImportValue 被评估AFTER Fn::Transform)以启用堆栈之间的串扰。

这可以通过 CloudFormation::Init 文件部分中的上下文键传递,如下所示:

"/etc/openvpn/server/openvpn.conf" : {
    "source": {
      "Fn::Sub": [
        "https://${BucketName}.s3.${Region}.amazonaws.com/Path/To/openvpn.conf.mustache",{
          "BucketName": "BucketNameGoesHere","Region": { "Ref": "AWS::Region" }
        }
      ]
    },"context": {
      "Vpn": {
        "Fn::Transform": {
          "Name": "NetworkInfo","Parameters": {
            "CIDR": { "Ref": "VpnCIDRRange"    }
          }
        }
      },"Aws": {
        "Fn::Transform": {
          "Name": "NetworkInfo","Parameters": {
            "CIDR-export": { "Fn::Sub": "${VPCName}-VPC-CIDR" }
          }
        }
      }
    }
  },

然后在实际的 mustache 模板中像这样引用:

push "route {{Aws.subnet}} {{Aws.netmask}}"