ec2_group - passing a list to a rule fails on subsequent runs.

453 views
Skip to first unread message

Aaron Mills

unread,
Sep 4, 2014, 7:46:24 PM9/4/14
to ansible...@googlegroups.com
Hi all,

I'm using Ansible 1.7 and trying to populate an ec2_group with a list of allowed IPs inbound. My playbook looks like so:

---
- name: Allow specific hosts to talk to my instance
  hosts: localhost
  connection: local
  vars:
    ec2_region: us-east-1
    vpc_id: vpc-12345
    sg_name: very-secure-group
    sg_description: A very secure group
    ips:
      - 1.2.3.4/32
      - 1.2.3.5/32
      - 1.2.3.6/32
      - 1.2.3.7/32
  tasks:
    - name: Create a very secure group
      local_action:
        module: ec2_group
        name: "{{ sg_name }}"
        description: "{{ sg_description }}"
        region: "{{ ec2_region }}"
        vpc_id: "{{ vpc_id }}"
        rules:
          - proto: tcp
            from_port: 443
            to_port: 443
            cidr_ip: "{{ ips }}"
          - proto: tcp
            from_port: 22
            to_port: 22
            cidr_ip: 6.7.8.9/32
        rules_egress:
          - proto: tcp
            from_port: 22
            to_port: 22
            cidr_ip: 6.7.8.9/32


The security group creates  just fine when I run this playbook. However, on subsequent runs, I get the following error from AWS/boto:

<Response><Errors><Error><Code>InvalidPermission.Duplicate</Code><Message>the specified rule "peer: 1.2.3.4/32, TCP, from port: 443, to port: 443, ALLOW" already exists</Message></Error></Errors><RequestID>blahblah</RequestID></Response>

So I can't re-run the playbook to add/remove rules. I know this is an AWS issue, but I'd prefer not to have to write a rule for each and every IP. I tried to do a "with_items" loop to generate the rules, but that also fails - it just adds a new rule over the top of the old one over and over (presumably because it calls the ec2_group module for every item?)

Is there another way to specify a rather lengthy list of IPs without having to create a rule for each one?

Many thanks.

James Cammarata

unread,
Sep 4, 2014, 11:30:50 PM9/4/14
to ansible...@googlegroups.com
Hi Aaron, is it valid to specify a list of IPs for the cidr_ip value in the rules (or was this a cut/paste mistake)?


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/fe92790b-8ca5-4331-8d61-7a6e6a39a73e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Aaron Mills

unread,
Sep 5, 2014, 11:38:06 AM9/5/14
to ansible...@googlegroups.com
It's valid. When you run a playbook that passes a list of IPs, it'll generate a rule for each IP in the list. However, when you run the playbook a second time, AWS throw's an error that those SG entries already exist. 

I was cribbing from Michael DeHaan's solution here. Looks like others have solved this with a template

James Cammarata

unread,
Sep 5, 2014, 3:36:31 PM9/5/14
to ansible...@googlegroups.com
I ask, because as far as I can tell from looking at the source code, we do not check that the cidr_ip may be a list of IPs rather than a single item. That means for things like this (where ip is the cidr_ip from the parsed rule data structure):

  ruleId = "%s-%s-%s-%s-%s-%s" % ('out', rule['proto'], rule['from_port'], rule['to_port'], group_id, ip)

The ruleId would seemingly be invalid, and the lookups/creation would not work as expected.

Alternatively to the template/include idea, 1.8 has added the params purge_rules and purge_rules_egrees, which when set to "no" means you should be able to add the rules in a loop without removing old rules.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Aaron Mills

unread,
Sep 5, 2014, 3:50:05 PM9/5/14
to ansible...@googlegroups.com
The purge functionality is actually quite nice for my use case, however. I'm dynamically gathering a list of hosts with a particular tag, then creating security group ingress rules to allow only those IPs (oh, the joys of VPC / public cloud inter-networking). So if a host is stopped/started, I need to get rid of the old IP and replace it with the new one when I run my playbook.

I solved this problem via the template method linked to previously. I'm not sure if updated Ansible code to loop through a list and create individual rules would be appropriate or not (I'm guessing not), so this may be the best method anyway.

Thanks for your help.

-Aaron

James Cammarata

unread,
Sep 5, 2014, 4:05:48 PM9/5/14
to ansible...@googlegroups.com
 No problem, feel free to open an issue on github for this too, as I'm pretty sure the module was not designed to work with a list of IPs natively like that (though maybe the AWS API will work the way we're stuffing those in there).

Thanks!


Reply all
Reply to author
Forward
0 new messages