diff --git a/changelogs/fragments/53732-iptables-add-iprange-support.yml b/changelogs/fragments/53732-iptables-add-iprange-support.yml new file mode 100644 index 00000000000..a29d2c1354e --- /dev/null +++ b/changelogs/fragments/53732-iptables-add-iprange-support.yml @@ -0,0 +1,3 @@ +--- +minor_changes: +- Added support for iptables module iprange and its parameters src-range and dst-range diff --git a/lib/ansible/modules/system/iptables.py b/lib/ansible/modules/system/iptables.py index 4352cd826de..7f6bbe7b06b 100644 --- a/lib/ansible/modules/system/iptables.py +++ b/lib/ansible/modules/system/iptables.py @@ -272,6 +272,16 @@ options: - Possible states are C(INVALID), C(NEW), C(ESTABLISHED), C(RELATED), C(UNTRACKED), C(SNAT), C(DNAT) type: list default: [] + src_range: + description: + - Specifies the source IP range to match in the iprange module. + type: str + version_added: "2.8" + dst_range: + description: + - Specifies the destination IP range to match in the iprange module. + type: str + version_added: "2.8" limit: description: - Specifies the maximum average number of matches to allow per second. @@ -360,6 +370,13 @@ EXAMPLES = r''' jump: ACCEPT comment: Accept new SSH connections. +- name: Match on IP ranges + iptables: + chain: FORWARD + src_range: 192.168.1.100-192.168.1.199 + dst_range: 10.0.0.1-10.0.0.50 + jump: ACCEPT + - name: Tag all outbound tcp packets with DSCP mark 8 iptables: chain: OUTPUT @@ -527,6 +544,13 @@ def construct_rule(params): elif params['ctstate']: append_match(rule, params['ctstate'], 'conntrack') append_csv(rule, params['ctstate'], '--ctstate') + if 'iprange' in params['match']: + append_param(rule, params['src_range'], '--src-range', False) + append_param(rule, params['dst_range'], '--dst-range', False) + elif params['src_range'] or params['dst_range']: + append_match(rule, params['src_range'] or params['dst_range'], 'iprange') + append_param(rule, params['src_range'], '--src-range', False) + append_param(rule, params['dst_range'], '--dst-range', False) append_match(rule, params['limit'] or params['limit_burst'], 'limit') append_param(rule, params['limit'], '--limit', False) append_param(rule, params['limit_burst'], '--limit-burst', False) @@ -639,6 +663,8 @@ def main(): set_dscp_mark_class=dict(type='str'), comment=dict(type='str'), ctstate=dict(type='list', default=[]), + src_range=dict(type='str'), + dst_range=dict(type='str'), limit=dict(type='str'), limit_burst=dict(type='str'), uid_owner=dict(type='str'), diff --git a/test/units/modules/system/test_iptables.py b/test/units/modules/system/test_iptables.py index d82beb089fe..a281864d7ae 100644 --- a/test/units/modules/system/test_iptables.py +++ b/test/units/modules/system/test_iptables.py @@ -729,3 +729,102 @@ class TestIptables(ModuleTestCase): '--log-prefix', '** DROP-this_ip **', '--log-level', log_lvl ]) + + def test_iprange(self): + """ Test iprange module with its flags src_range and dst_range """ + set_module_args({ + 'chain': 'INPUT', + 'match': ['iprange'], + 'src_range': '192.168.1.100-192.168.1.199', + 'jump': 'ACCEPT' + }) + + commands_results = [ + (0, '', ''), + ] + + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.side_effect = commands_results + with self.assertRaises(AnsibleExitJson) as result: + iptables.main() + self.assertTrue(result.exception.args[0]['changed']) + + self.assertEqual(run_command.call_count, 1) + self.assertEqual(run_command.call_args_list[0][0][0], [ + '/sbin/iptables', + '-t', + 'filter', + '-C', + 'INPUT', + '-m', + 'iprange', + '-j', + 'ACCEPT', + '--src-range', + '192.168.1.100-192.168.1.199', + ]) + + set_module_args({ + 'chain': 'INPUT', + 'src_range': '192.168.1.100-192.168.1.199', + 'dst_range': '10.0.0.50-10.0.0.100', + 'jump': 'ACCEPT' + }) + + commands_results = [ + (0, '', ''), + ] + + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.side_effect = commands_results + with self.assertRaises(AnsibleExitJson) as result: + iptables.main() + self.assertTrue(result.exception.args[0]['changed']) + + self.assertEqual(run_command.call_count, 1) + self.assertEqual(run_command.call_args_list[0][0][0], [ + '/sbin/iptables', + '-t', + 'filter', + '-C', + 'INPUT', + '-j', + 'ACCEPT', + '-m', + 'iprange', + '--src-range', + '192.168.1.100-192.168.1.199', + '--dst-range', + '10.0.0.50-10.0.0.100' + ]) + + set_module_args({ + 'chain': 'INPUT', + 'dst_range': '10.0.0.50-10.0.0.100', + 'jump': 'ACCEPT' + }) + + commands_results = [ + (0, '', ''), + ] + + with patch.object(basic.AnsibleModule, 'run_command') as run_command: + run_command.side_effect = commands_results + with self.assertRaises(AnsibleExitJson) as result: + iptables.main() + self.assertTrue(result.exception.args[0]['changed']) + + self.assertEqual(run_command.call_count, 1) + self.assertEqual(run_command.call_args_list[0][0][0], [ + '/sbin/iptables', + '-t', + 'filter', + '-C', + 'INPUT', + '-j', + 'ACCEPT', + '-m', + 'iprange', + '--dst-range', + '10.0.0.50-10.0.0.100' + ])