diff --git a/changelogs/fragments/53170-iptables-support_gateway.yml b/changelogs/fragments/53170-iptables-support_gateway.yml new file mode 100644 index 0000000000..67dad21fd4 --- /dev/null +++ b/changelogs/fragments/53170-iptables-support_gateway.yml @@ -0,0 +1,2 @@ +minor_changes: +- Added support for gateway parameter in iptables module (https://github.com/ansible/ansible/issues/53170). diff --git a/lib/ansible/modules/system/iptables.py b/lib/ansible/modules/system/iptables.py index 6eeddd719c..8489ec2f58 100644 --- a/lib/ansible/modules/system/iptables.py +++ b/lib/ansible/modules/system/iptables.py @@ -145,6 +145,12 @@ options: is not used), then matching the rule will have no effect on the packet's fate, but the counters on the rule will be incremented. type: str + gateway: + description: + - This specifies the IP address of host to send the cloned packets. + - This option is only valid when C(jump) is set to C(TEE). + type: str + version_added: "2.8" log_prefix: description: - Specifies a log text for the rule. Only make sense with a LOG jump. @@ -473,6 +479,8 @@ def construct_rule(params): append_param(rule, params['match'], '-m', True) append_tcp_flags(rule, params['tcp_flags'], '--tcp-flags') append_param(rule, params['jump'], '-j', False) + if params.get('jump') and params['jump'].lower() == 'tee': + append_param(rule, params['gateway'], '--gateway', False) append_param(rule, params['log_prefix'], '--log-prefix', False) append_param(rule, params['to_destination'], '--to-destination', False) append_param(rule, params['to_source'], '--to-source', False) @@ -592,6 +600,7 @@ def main(): flags_set=dict(type='list')) ), jump=dict(type='str'), + gateway=dict(type='str'), log_prefix=dict(type='str'), goto=dict(type='str'), in_interface=dict(type='str'), @@ -618,6 +627,10 @@ def main(): ['set_dscp_mark', 'set_dscp_mark_class'], ['flush', 'policy'], ), + required_if=[ + ['jump', 'TEE', ['gateway']], + ['jump', 'tee', ['gateway']], + ] ) args = dict( changed=False, diff --git a/test/units/modules/system/test_iptables.py b/test/units/modules/system/test_iptables.py index 1e1ec34383..dae3c1d2f0 100644 --- a/test/units/modules/system/test_iptables.py +++ b/test/units/modules/system/test_iptables.py @@ -578,6 +578,64 @@ class TestIptables(ModuleTestCase): 'tcp-reset', ]) + def test_jump_tee_gateway_negative(self): + """ Missing gateway when JUMP is set to TEE """ + set_module_args({ + 'table': 'mangle', + 'chain': 'PREROUTING', + 'in_interface': 'eth0', + 'protocol': 'udp', + 'match': 'state', + 'jump': 'TEE', + 'ctstate': ['NEW'], + 'destination_port': '9521', + 'destination': '127.0.0.1' + }) + + with self.assertRaises(AnsibleFailJson) as e: + iptables.main() + self.assertTrue(e.exception.args[0]['failed']) + self.assertEqual(e.exception.args[0]['msg'], 'jump is TEE but all of the following are missing: gateway') + + def test_jump_tee_gateway(self): + """ Using gateway when JUMP is set to TEE """ + set_module_args({ + 'table': 'mangle', + 'chain': 'PREROUTING', + 'in_interface': 'eth0', + 'protocol': 'udp', + 'match': 'state', + 'jump': 'TEE', + 'ctstate': ['NEW'], + 'destination_port': '9521', + 'gateway': '192.168.10.1', + 'destination': '127.0.0.1' + }) + 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', 'mangle', + '-C', 'PREROUTING', + '-p', 'udp', + '-d', '127.0.0.1', + '-m', 'state', + '-j', 'TEE', + '--gateway', '192.168.10.1', + '-i', 'eth0', + '--destination-port', '9521', + '--state', 'NEW' + ]) + def test_tcp_flags(self): """ Test various ways of inputting tcp_flags """ args = [