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:
parent
41713d0819
commit
73cf1f2755
1 changed files with 93 additions and 20 deletions
|
@ -74,8 +74,8 @@ options:
|
||||||
description:
|
description:
|
||||||
- "Chain to operate on. This option can either be the name of a user
|
- "Chain to operate on. This option can either be the name of a user
|
||||||
defined chain or any of the builtin chains: 'INPUT', 'FORWARD',
|
defined chain or any of the builtin chains: 'INPUT', 'FORWARD',
|
||||||
'OUTPUT', 'PREROUTING', 'POSTROUTING', 'SECMARK', 'CONNSECMARK'"
|
'OUTPUT', 'PREROUTING', 'POSTROUTING', 'SECMARK', 'CONNSECMARK'."
|
||||||
required: true
|
required: false
|
||||||
protocol:
|
protocol:
|
||||||
description:
|
description:
|
||||||
- The protocol of the rule or of the packet to check. The specified
|
- The protocol of the rule or of the packet to check. The specified
|
||||||
|
@ -240,13 +240,18 @@ options:
|
||||||
default: null
|
default: null
|
||||||
ctstate:
|
ctstate:
|
||||||
description:
|
description:
|
||||||
- "ctstate is a list of the connection states to match in the conntrack module.
|
- "ctstate is a list of the connection states to match in the conntrack
|
||||||
Possible states are: 'INVALID', 'NEW', 'ESTABLISHED', 'RELATED', 'UNTRACKED', 'SNAT', 'DNAT'"
|
module.
|
||||||
|
Possible states are: 'INVALID', 'NEW', 'ESTABLISHED', 'RELATED',
|
||||||
|
'UNTRACKED', 'SNAT', 'DNAT'"
|
||||||
required: false
|
required: false
|
||||||
default: []
|
default: []
|
||||||
limit:
|
limit:
|
||||||
description:
|
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
|
required: false
|
||||||
default: null
|
default: null
|
||||||
limit_burst:
|
limit_burst:
|
||||||
|
@ -268,10 +273,24 @@ options:
|
||||||
icmp_type:
|
icmp_type:
|
||||||
version_added: "2.2"
|
version_added: "2.2"
|
||||||
description:
|
description:
|
||||||
- "This allows specification of the ICMP type, which can be a numeric ICMP type,
|
- "This allows specification of the ICMP type, which can be a numeric
|
||||||
type/code pair, or one of the ICMP type names shown by the command
|
ICMP type, type/code pair, or one of the ICMP type names shown by the
|
||||||
'iptables -p icmp -h'"
|
command 'iptables -p icmp -h'"
|
||||||
required: false
|
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 = '''
|
EXAMPLES = '''
|
||||||
|
@ -337,7 +356,11 @@ def construct_rule(params):
|
||||||
append_param(rule, params['destination_port'], '--destination-port', False)
|
append_param(rule, params['destination_port'], '--destination-port', False)
|
||||||
append_param(rule, params['to_ports'], '--to-ports', 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'], '--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_match(rule, params['comment'], 'comment')
|
||||||
append_param(rule, params['comment'], '--comment', False)
|
append_param(rule, params['comment'], '--comment', False)
|
||||||
append_match(rule, params['ctstate'], 'state')
|
append_match(rule, params['ctstate'], 'state')
|
||||||
|
@ -353,11 +376,12 @@ def construct_rule(params):
|
||||||
return rule
|
return rule
|
||||||
|
|
||||||
|
|
||||||
def push_arguments(iptables_path, action, params):
|
def push_arguments(iptables_path, action, params, make_rule=True):
|
||||||
cmd = [iptables_path]
|
cmd = [iptables_path]
|
||||||
cmd.extend(['-t', params['table']])
|
cmd.extend(['-t', params['table']])
|
||||||
cmd.extend([action, params['chain']])
|
cmd.extend([action, params['chain']])
|
||||||
cmd.extend(construct_rule(params))
|
if make_rule:
|
||||||
|
cmd.extend(construct_rule(params))
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
@ -382,15 +406,39 @@ def remove_rule(iptables_path, module, params):
|
||||||
module.run_command(cmd, check_rc=True)
|
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():
|
def main():
|
||||||
module = AnsibleModule(
|
module = AnsibleModule(
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
argument_spec=dict(
|
argument_spec=dict(
|
||||||
table=dict(required=False, default='filter', choices=['filter', 'nat', 'mangle', 'raw', 'security']),
|
table=dict(
|
||||||
state=dict(required=False, default='present', choices=['present', 'absent']),
|
required=False,
|
||||||
action=dict(required=False, default='append', type='str', choices=['append', 'insert']),
|
default='filter',
|
||||||
ip_version=dict(required=False, default='ipv4', choices=['ipv4', 'ipv6']),
|
choices=['filter', 'nat', 'mangle', 'raw', 'security']),
|
||||||
chain=dict(required=True, default=None, type='str'),
|
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'),
|
protocol=dict(required=False, default=None, type='str'),
|
||||||
source=dict(required=False, default=None, type='str'),
|
source=dict(required=False, default=None, type='str'),
|
||||||
to_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'),
|
source_port=dict(required=False, default=None, type='str'),
|
||||||
destination_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'),
|
to_ports=dict(required=False, default=None, type='str'),
|
||||||
set_dscp_mark=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_class=dict(required=False, default=None, type='str'),
|
||||||
comment=dict(required=False, default=None, type='str'),
|
comment=dict(required=False, default=None, type='str'),
|
||||||
ctstate=dict(required=False, default=[], type='list'),
|
ctstate=dict(required=False, default=[], type='list'),
|
||||||
limit=dict(required=False, default=None, type='str'),
|
limit=dict(required=False, default=None, type='str'),
|
||||||
|
@ -415,9 +463,16 @@ def main():
|
||||||
uid_owner=dict(required=False, default=None, type='str'),
|
uid_owner=dict(required=False, default=None, type='str'),
|
||||||
reject_with=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'),
|
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=(
|
mutually_exclusive=(
|
||||||
['set_dscp_mark', 'set_dscp_mark_class'],
|
['set_dscp_mark', 'set_dscp_mark_class'],
|
||||||
|
['flush', 'policy'],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
args = dict(
|
args = dict(
|
||||||
|
@ -426,12 +481,30 @@ def main():
|
||||||
ip_version=module.params['ip_version'],
|
ip_version=module.params['ip_version'],
|
||||||
table=module.params['table'],
|
table=module.params['table'],
|
||||||
chain=module.params['chain'],
|
chain=module.params['chain'],
|
||||||
|
flush=module.params['flush'],
|
||||||
rule=' '.join(construct_rule(module.params)),
|
rule=' '.join(construct_rule(module.params)),
|
||||||
state=module.params['state'],
|
state=module.params['state'],
|
||||||
)
|
)
|
||||||
insert = (module.params['action'] == 'insert')
|
|
||||||
ip_version = module.params['ip_version']
|
ip_version = module.params['ip_version']
|
||||||
iptables_path = module.get_bin_path(BINS[ip_version], True)
|
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)
|
rule_is_present = check_present(iptables_path, module, module.params)
|
||||||
should_be_present = (args['state'] == 'present')
|
should_be_present = (args['state'] == 'present')
|
||||||
|
|
||||||
|
@ -443,7 +516,7 @@ def main():
|
||||||
module.exit_json(changed=args['changed'])
|
module.exit_json(changed=args['changed'])
|
||||||
|
|
||||||
# Target is already up to date
|
# Target is already up to date
|
||||||
if args['changed'] == False:
|
if args['changed'] is False:
|
||||||
module.exit_json(**args)
|
module.exit_json(**args)
|
||||||
|
|
||||||
if should_be_present:
|
if should_be_present:
|
||||||
|
|
Loading…
Reference in a new issue