diff --git a/changelogs/fragments/398-ec2-vpc-nacl-add-ipv6.yaml b/changelogs/fragments/398-ec2-vpc-nacl-add-ipv6.yaml new file mode 100644 index 00000000000..2b324a0c36d --- /dev/null +++ b/changelogs/fragments/398-ec2-vpc-nacl-add-ipv6.yaml @@ -0,0 +1,2 @@ +minor_changes: + - ec2_vpc_nacl - add support for IPv6 (https://github.com/ansible-collections/community.aws/pull/398). diff --git a/plugins/modules/ec2_vpc_nacl.py b/plugins/modules/ec2_vpc_nacl.py index 387ceb48f26..da053f55a46 100644 --- a/plugins/modules/ec2_vpc_nacl.py +++ b/plugins/modules/ec2_vpc_nacl.py @@ -43,8 +43,8 @@ egress: description: - A list of rules for outgoing traffic. Each rule must be specified as a list. - Each rule may contain the rule number (integer 1-32766), protocol (one of ['tcp', 'udp', 'icmp', '-1', 'all']), - the rule action ('allow' or 'deny') the CIDR of the IPv4 network range to allow or deny, + Each rule may contain the rule number (integer 1-32766), protocol (one of ['tcp', 'udp', 'icmp', 'ipv6-icmp', '-1', 'all']), + the rule action ('allow' or 'deny') the CIDR of the IPv4 or IPv6 network range to allow or deny, the ICMP type (-1 means all types), the ICMP code (-1 means all codes), the last port in the range for TCP or UDP protocols, and the first port in the range for TCP or UDP protocols. See examples. @@ -55,8 +55,8 @@ ingress: description: - List of rules for incoming traffic. Each rule must be specified as a list. - Each rule may contain the rule number (integer 1-32766), protocol (one of ['tcp', 'udp', 'icmp', '-1', 'all']), - the rule action ('allow' or 'deny') the CIDR of the IPv4 network range to allow or deny, + Each rule may contain the rule number (integer 1-32766), protocol (one of ['tcp', 'udp', 'icmp', 'ipv6-icmp', '-1', 'all']), + the rule action ('allow' or 'deny') the CIDR of the IPv4 or IPv6 network range to allow or deny, the ICMP type (-1 means all types), the ICMP code (-1 means all codes), the last port in the range for TCP or UDP protocols, and the first port in the range for TCP or UDP protocols. See examples. @@ -104,9 +104,12 @@ # port from, port to - [100, 'tcp', 'allow', '0.0.0.0/0', null, null, 22, 22] - [200, 'tcp', 'allow', '0.0.0.0/0', null, null, 80, 80] + - [205, 'tcp', 'allow', '::/0', null, null, 80, 80] - [300, 'icmp', 'allow', '0.0.0.0/0', 0, 8] + - [305, 'ipv6-icmp', 'allow', '::/0', 0, 8] egress: - [100, 'all', 'allow', '0.0.0.0/0', null, null, null, null] + - [105, 'all', 'allow', '::/0', null, null, null, null] state: 'present' - name: "Remove the ingress and egress rules - defaults to deny all" @@ -163,12 +166,12 @@ # VPC-supported IANA protocol numbers # http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml -PROTOCOL_NUMBERS = {'all': -1, 'icmp': 1, 'tcp': 6, 'udp': 17, } +PROTOCOL_NUMBERS = {'all': -1, 'icmp': 1, 'tcp': 6, 'udp': 17, 'ipv6-icmp': 58} # Utility methods def icmp_present(entry): - if len(entry) == 6 and entry[1] == 'icmp' or entry[1] == 1: + if len(entry) == 6 and entry[1] in ['icmp', 'ipv6-icmp'] or entry[1] in [1, 58]: return True @@ -291,13 +294,20 @@ def rules_changed(aws_rules, param_rules, Egress, nacl_id, client, module): return changed +def is_ipv6(cidr): + return ':' in cidr + + def process_rule_entry(entry, Egress): params = dict() params['RuleNumber'] = entry[0] params['Protocol'] = str(PROTOCOL_NUMBERS[entry[1]]) params['RuleAction'] = entry[2] params['Egress'] = Egress - params['CidrBlock'] = entry[3] + if is_ipv6(entry[3]): + params['Ipv6CidrBlock'] = entry[3] + else: + params['CidrBlock'] = entry[3] if icmp_present(entry): params['IcmpTypeCode'] = {"Type": int(entry[4]), "Code": int(entry[5])} else: diff --git a/tests/integration/targets/ec2_vpc_nacl/tasks/ipv6.yml b/tests/integration/targets/ec2_vpc_nacl/tasks/ipv6.yml index 16b3a5aaaff..59634c0d429 100644 --- a/tests/integration/targets/ec2_vpc_nacl/tasks/ipv6.yml +++ b/tests/integration/targets/ec2_vpc_nacl/tasks/ipv6.yml @@ -62,7 +62,7 @@ ingress: - [100, 'tcp', 'allow', '0.0.0.0/0', null, null, 22, 22] - [200, 'tcp', 'allow', '0.0.0.0/0', null, null, 80, 80] - - [205, 'ipv6-tcp', 'allow', '::/0', null, null, 80, 80] + - [205, 'tcp', 'allow', '::/0', null, null, 80, 80] - [300, 'icmp', 'allow', '0.0.0.0/0', 0, 8] - [305, 'ipv6-icmp', 'allow', '::/0', 0, 8] egress: @@ -70,20 +70,24 @@ - [105, 'all', 'allow', '::/0', null, null, null, null] state: 'present' register: nacl - # FIXME: Currently IPv6 rules are not supported - uncomment assertion when - # fixed (and add some nacl_info tests) - ignore_errors: yes + + - assert: + that: + - nacl.changed + - nacl.nacl_id == nacl_id + - name: get network ACL facts (test that it works with ipv6 entries) ec2_vpc_nacl_info: nacl_ids: - "{{ nacl_id }}" register: nacl_facts - - #- assert: - # that: - # - nacl.changed - # - nacl.nacl_id == nacl_id + - name: assert the nacl has the correct attributes + assert: + that: + - nacl_facts.nacls | length == 1 + - nacl_facts.nacls[0].ingress | length == 5 + - nacl_facts.nacls[0].egress | length == 2 - name: purge ingress entries ec2_vpc_nacl: @@ -99,14 +103,11 @@ - [105, 'all', 'allow', '::/0', null, null, null, null] state: 'present' register: nacl - # FIXME: Currently IPv6 rules are not supported - uncomment assertion when - # fixed (and add some nacl_info tests) - ignore_errors: yes - #- assert: - # that: - # - nacl.changed - # - nacl.nacl_id == nacl_id + - assert: + that: + - nacl.changed + - nacl.nacl_id == nacl_id - name: purge egress entries ec2_vpc_nacl: @@ -125,6 +126,19 @@ that: - nacl.changed + - name: get network ACL facts (test that removed entries are gone) + ec2_vpc_nacl_info: + nacl_ids: + - "{{ nacl_id }}" + register: nacl_facts + + - name: assert the nacl has the correct attributes + assert: + that: + - nacl_facts.nacls | length == 1 + - nacl_facts.nacls[0].ingress | length == 0 + - nacl_facts.nacls[0].egress | length == 0 + # ============================================================ - name: remove subnet ipv6 cidr (expected changed=true) ec2_vpc_subnet: