amazon-web-services – 在Ansible playbook中替换EC2安全组规则中的变量

我正在尝试使用Ansible来配置AWS EC2安全组.

我希望其中一些组有多个规则.有些规则仅适用于我的内部VPC,而其他规则则适用于全世界.

我想在一个从列表变量中读取配置的循环中创建安全组,但我不想为内部VPC硬编码CIDR.我宁愿从我的VPC事实中获得CIDR,但我还没有找到一种令人满意的方法来将CIDR替换为规则.

为了更清楚,这是一个(人为的)例子.我原来的小组列表中所有的CIDR都是硬编码的:

aws_security_groups:
  - name: Webservers
    description: Security group for webservers
    region: my_aws_region
    rules: 
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        from_port: 80
        to_port: 80
        cidr_ip: 0.0.0.0/0
  - name: Databases
    description: Security group for internal database access
    region: my_aws_region
    rules: 
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: 0.0.0.0/0
      - proto: tcp
        from_port: 3306
        to_port: 3306
        cidr_ip: <vpc.cidr.hard.coded/16>

原作很有效,非常简单:

- name: Provision EC2 security groups
  ec2_group:
    name: "{{ item.name }}"
    description: "{{ item.description }}"
    region: "{{ item.region }}"
    state: present
    rules: "{{ item.rules }}"
  with_items: "{{ aws_security_groups }}"

我可以添加或减去规则,并知道这些组将被同步.但是,我不想硬编码CIDR …我希望我的组列表看起来像:

aws_security_groups:
  - name: Webservers
    description: Security group for webservers
    region: my_aws_region
    rules: 
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: all
      - proto: tcp
        from_port: 80
        to_port: 80
        cidr_ip: all

  - name: Databases
    description: Security group for internal database access
    region: my_aws_region
    rules: 
      - proto: tcp
        from_port: 22
        to_port: 22
        cidr_ip: all
      - proto: tcp
        from_port: 3306
        to_port: 3306
        cidr_ip: internal

我目前的策略是使用with_subelements为每个规则分别运行一堆ec2_group命令:

- name: Gather EC2 VPC facts
  ec2_vpc_net_facts:
    region: my_aws_region
  register: vpcs

- name: Provision EC2 security groups
  ec2_group:
    name: "{{ item.0.name }}"
    description: "{{ item.0.description }}"
    region: "{{ item.0.region }}"
    state: present
    purge_rules: false
    rules: 
      - from_port: "{{ item.1.from_port }}"
        to_port: "{{ item.1.to_port }}"
        proto: "{{ item.1.proto }}"
        cidr_ip: "{{ (item.1.cidr_ip == 'internal') | ternary(vpcs.vpcs.0.cidr_block, (item.1.cidr_ip == 'all') | ternary('0.0.0.0/0', item.1.cidr_ip)) }}"
  with_subelements: 
    - "{{ aws_security_groups }}"
    - rules

替换工作,但我有一些不舒服的权衡.

首先,我必须关闭purge_rules,因为如果不这样做,每个循环都会删除先前的规则.因此,如果我对规则进行更改,我可能会遇到旧规则,我需要跟踪和清理.

其次,嵌套的三元组很笨拙,不易扩展.

第三,当一个人足够时,我正在打多个电话.

我觉得我错过了一些显而易见的东西,或者说我过于复杂了.如何在Ansible剧本中完成CIDR替换,或更一般地说,这种替换?替代是优选的还是有更好的方法来完成相同的任务?

非常感谢任何帮助.

最佳答案 以下方法可以避免purge_rules问题,而且更清洁,imho.

任务:

- set_fact:
    from_template: "{{ lookup('template', './template.j2') }}"
  vars:
    to_template_aws_security_groups: "{{ aws_security_groups }}"
    to_template_vpcs: "{{ vpcs }}"

- name: Provision EC2 security groups
  ec2_group:
    name: "{{ item.name }}"
    description: "{{ item.description }}"
    region: "{{ item.region }}"
    state: present
    rules: "{{ item.rules }}"
  with_items: "{{ from_template.aws_security_groups }}"

template.j2:

{
  "aws_security_groups": [
    {% for aws_security_group in to_template_aws_security_groups %}
    {
      "description": "{{ aws_security_group.description }}",
      "name": "{{ aws_security_group.name }}",
      "region": "{{ aws_security_group.region }}",
      "rules": [
        {% for rule in aws_security_group.rules %}
        {
          "cidr_ip": "{{ (rule.cidr_ip == 'internal') | ternary(to_template_vpcs.vpcs.0.cidr_block, (rule.cidr_ip == 'all') | ternary('0.0.0.0/0', rule.cidr_ip)) }}",
          "from_port": "{{ rule.from_port }}",
          "proto": "{{ rule.proto }}",
          "to_port": {{ rule.to_port }}
        }{% if not loop.last %},{% endif %}
        {% endfor %}
      ]
    }{% if not loop.last %},{% endif %}
    {% endfor %}
  ]
}
点赞