Iptables enhancements (#2789)

* Add the flush parameter.

When specified the flush parameter indicates that this module should remove all
rules from the specified table. If no table parameter is specified then the
default filter table is flushed.

* Add support for setting chain policies.

The module supports setting the policy of a given chain and table to the
following target values, ACCEPT, DROP, QUEUE, and RETURN. This parameter ignores
all other unrelated parameters.

* Fix pep8 issues.

* Fix missing quotation.

* Make 'flush' and 'policy' parameters mutually exclusive.

This combination is not supported by the wrapped iptables command. 'flush' and
'policy' however, can both take the 'chain' argument.
This commit is contained in:
Mike Liu 2016-08-30 10:16:10 -04:00 committed by Matt Clay
parent 41713d0819
commit 73cf1f2755

View file

@ -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,10 +376,11 @@ 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']])
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: