diff --git a/lib/ansible/modules/extras/system/iptables.py b/lib/ansible/modules/extras/system/iptables.py index 51089575456..5d055182367 100644 --- a/lib/ansible/modules/extras/system/iptables.py +++ b/lib/ansible/modules/extras/system/iptables.py @@ -74,8 +74,8 @@ options: description: - "Chain to operate on. This option can either be the name of a user defined chain or any of the builtin chains: 'INPUT', 'FORWARD', - 'OUTPUT', 'PREROUTING', 'POSTROUTING', 'SECMARK', 'CONNSECMARK'" - required: true + 'OUTPUT', 'PREROUTING', 'POSTROUTING', 'SECMARK', 'CONNSECMARK'." + required: false protocol: description: - The protocol of the rule or of the packet to check. The specified @@ -240,13 +240,18 @@ options: default: null ctstate: description: - - "ctstate is a list of the connection states to match in the conntrack module. - Possible states are: 'INVALID', 'NEW', 'ESTABLISHED', 'RELATED', 'UNTRACKED', 'SNAT', 'DNAT'" + - "ctstate is a list of the connection states to match in the conntrack + module. + Possible states are: 'INVALID', 'NEW', 'ESTABLISHED', 'RELATED', + 'UNTRACKED', 'SNAT', 'DNAT'" required: false default: [] limit: description: - - "Specifies the maximum average number of matches to allow per second. The number can specify units explicitly, using `/second', `/minute', `/hour' or `/day', or parts of them (so `5/second' is the same as `5/s')." + - "Specifies the maximum average number of matches to allow per second. + The number can specify units explicitly, using `/second', `/minute', + `/hour' or `/day', or parts of them (so `5/second' is the same as + `5/s')." required: false default: null limit_burst: @@ -268,10 +273,24 @@ options: icmp_type: version_added: "2.2" description: - - "This allows specification of the ICMP type, which can be a numeric ICMP type, - type/code pair, or one of the ICMP type names shown by the command - 'iptables -p icmp -h'" + - "This allows specification of the ICMP type, which can be a numeric + ICMP type, type/code pair, or one of the ICMP type names shown by the + command 'iptables -p icmp -h'" required: false + flush: + version_added: "2.2" + description: + - "Flushes the specified table and chain of all rules. If no chain is + specified then the entire table is purged. Ignores all other + parameters." + required: false + policy: + version_added: "2.2" + description: + - "Set the policy for the chain to the given target. Valid targets are + ACCEPT, DROP, QUEUE, RETURN. Only built in chains can have policies. + This parameter requires the chain parameter. Ignores all other + parameters." ''' EXAMPLES = ''' @@ -337,7 +356,11 @@ def construct_rule(params): append_param(rule, params['destination_port'], '--destination-port', False) append_param(rule, params['to_ports'], '--to-ports', False) append_param(rule, params['set_dscp_mark'], '--set-dscp', False) - append_param(rule, params['set_dscp_mark_class'], '--set-dscp-class', False) + append_param( + rule, + params['set_dscp_mark_class'], + '--set-dscp-class', + False) append_match(rule, params['comment'], 'comment') append_param(rule, params['comment'], '--comment', False) append_match(rule, params['ctstate'], 'state') @@ -353,11 +376,12 @@ def construct_rule(params): return rule -def push_arguments(iptables_path, action, params): +def push_arguments(iptables_path, action, params, make_rule=True): cmd = [iptables_path] cmd.extend(['-t', params['table']]) cmd.extend([action, params['chain']]) - cmd.extend(construct_rule(params)) + if make_rule: + cmd.extend(construct_rule(params)) return cmd @@ -382,15 +406,39 @@ def remove_rule(iptables_path, module, params): module.run_command(cmd, check_rc=True) +def flush_table(iptables_path, module, params): + cmd = push_arguments(iptables_path, '-F', params, make_rule=False) + module.run_command(cmd, check_rc=True) + + +def set_chain_policy(iptables_path, module, params): + cmd = push_arguments(iptables_path, '-P', params, make_rule=False) + cmd.append(params['policy']) + module.run_command(cmd, check_rc=True) + + def main(): module = AnsibleModule( supports_check_mode=True, argument_spec=dict( - table=dict(required=False, default='filter', choices=['filter', 'nat', 'mangle', 'raw', 'security']), - state=dict(required=False, default='present', choices=['present', 'absent']), - action=dict(required=False, default='append', type='str', choices=['append', 'insert']), - ip_version=dict(required=False, default='ipv4', choices=['ipv4', 'ipv6']), - chain=dict(required=True, default=None, type='str'), + table=dict( + required=False, + default='filter', + choices=['filter', 'nat', 'mangle', 'raw', 'security']), + state=dict( + required=False, + default='present', + choices=['present', 'absent']), + action=dict( + required=False, + default='append', + type='str', + choices=['append', 'insert']), + ip_version=dict( + required=False, + default='ipv4', + choices=['ipv4', 'ipv6']), + chain=dict(required=False, default=None, type='str'), protocol=dict(required=False, default=None, type='str'), source=dict(required=False, default=None, type='str'), to_source=dict(required=False, default=None, type='str'), @@ -406,8 +454,8 @@ def main(): source_port=dict(required=False, default=None, type='str'), destination_port=dict(required=False, default=None, type='str'), to_ports=dict(required=False, default=None, type='str'), - set_dscp_mark=dict(required=False,default=None, type='str'), - set_dscp_mark_class=dict(required=False,default=None, type='str'), + set_dscp_mark=dict(required=False, default=None, type='str'), + set_dscp_mark_class=dict(required=False, default=None, type='str'), comment=dict(required=False, default=None, type='str'), ctstate=dict(required=False, default=[], type='list'), limit=dict(required=False, default=None, type='str'), @@ -415,9 +463,16 @@ def main(): uid_owner=dict(required=False, default=None, type='str'), reject_with=dict(required=False, default=None, type='str'), icmp_type=dict(required=False, default=None, type='str'), + flush=dict(required=False, default=False, type='bool'), + policy=dict( + required=False, + default=None, + type='str', + choices=['ACCEPT', 'DROP', 'QUEUE', 'RETURN']), ), mutually_exclusive=( ['set_dscp_mark', 'set_dscp_mark_class'], + ['flush', 'policy'], ), ) args = dict( @@ -426,12 +481,30 @@ def main(): ip_version=module.params['ip_version'], table=module.params['table'], chain=module.params['chain'], + flush=module.params['flush'], rule=' '.join(construct_rule(module.params)), state=module.params['state'], ) - insert = (module.params['action'] == 'insert') + ip_version = module.params['ip_version'] iptables_path = module.get_bin_path(BINS[ip_version], True) + + # Check if chain option is required + if args['flush'] is False and args['chain'] is None: + module.fail_json( + msg="Either chain or flush parameter must be specified.") + + # Flush the table + if args['flush'] is True: + flush_table(iptables_path, module, module.params) + module.exit_json(**args) + + # Set the policy + if module.params['policy']: + set_chain_policy(iptables_path, module, module.params) + module.exit_json(**args) + + insert = (module.params['action'] == 'insert') rule_is_present = check_present(iptables_path, module, module.params) should_be_present = (args['state'] == 'present') @@ -443,7 +516,7 @@ def main(): module.exit_json(changed=args['changed']) # Target is already up to date - if args['changed'] == False: + if args['changed'] is False: module.exit_json(**args) if should_be_present: