@ -71,9 +71,12 @@ options:
version_added : " 1.9 "
state :
description :
- " Should this port accept(enabled) or reject(disabled) connections. "
- >
Enable or disable a setting .
For ports : Should this port accept ( enabled ) or reject ( disabled ) connections .
The states " present " and " absent " can only be used in zone level operations ( i . e . when no other parameters but zone and state are set ) .
required : true
choices : [ " enabled " , " disabled " ]
choices : [ " enabled " , " disabled " , " present " , " absent " ]
timeout :
description :
- " The amount of time the rule should be in effect for when non-permanent. "
@ -88,6 +91,12 @@ options:
notes :
- Not tested on any Debian based system .
- Requires the python2 bindings of firewalld , which may not be installed by default if the distribution switched to python 3
- Zone transactions ( creating , deleting ) can be performed by using only the zone and state parameters " present " or " absent " .
Note that zone transactions must explicitly be permanent . This is a limitation in firewalld .
This also means that you will have to reload firewalld after adding a zone that you wish to perfom immediate actions on .
The module will not take care of this for you implicitly because that would undo any previously performed immediate actions which were not
permanent . Therefor , if you require immediate access to a newly created zone it is recommended you reload firewalld immediately after the zone
creation returns with a changed state and before you perform any other immediate , non - permanent actions on that zone .
requirements : [ ' firewalld >= 0.2.11 ' ]
author : " Adam Miller (@maxamillion) "
'''
@ -135,6 +144,11 @@ EXAMPLES = '''
state : enabled
permanent : true
zone : dmz
- firewalld :
zone : custom
state : present
permanent : true
'''
from ansible . module_utils . basic import AnsibleModule
@ -149,6 +163,7 @@ try:
from firewall . client import Rich_Rule
from firewall . client import FirewallClient
from firewall . client import FirewallClientZoneSettings
fw = None
fw_offline = False
import_failure = False
@ -165,7 +180,6 @@ try:
# NOTE:
# online and offline operations do not share a common firewalld API
from firewall . core . fw_test import Firewall_test
from firewall . client import FirewallClientZoneSettings
fw = Firewall_test ( )
fw . start ( )
@ -183,7 +197,8 @@ class FirewallTransaction(object):
global module
def __init__ ( self , fw , action_args = ( ) , zone = None , desired_state = None ,
permanent = False , immediate = False , fw_offline = False ) :
permanent = False , immediate = False , fw_offline = False ,
enabled_values = None , disabled_values = None ) :
# type: (firewall.client, tuple, str, bool, bool, bool)
"""
initializer the transaction
@ -195,6 +210,8 @@ class FirewallTransaction(object):
: permanent : bool , action should be permanent
: immediate : bool , action should take place immediately
: fw_offline : bool , action takes place as if the firewall were offline
: enabled_values : str [ ] , acceptable values for enabling something ( default : enabled )
: disabled_values : str [ ] , acceptable values for disabling something ( default : disabled )
"""
self . fw = fw
@ -204,6 +221,8 @@ class FirewallTransaction(object):
self . permanent = permanent
self . immediate = immediate
self . fw_offline = fw_offline
self . enabled_values = enabled_values or [ " enabled " ]
self . disabled_values = disabled_values or [ " disabled " ]
# List of messages that we'll call module.fail_json or module.exit_json
# with.
@ -214,12 +233,6 @@ class FirewallTransaction(object):
self . enabled_msg = None
self . disabled_msg = None
# List of acceptable values to enable/diable something
# Right now these are only 1 each but in the event we want to add more
# later, this will make it easy.
self . enabled_values = [ " enabled " ]
self . disabled_values = [ " disabled " ]
#####################
# exception handling
#
@ -728,6 +741,52 @@ class SourceTransaction(FirewallTransaction):
self . update_fw_settings ( fw_zone , fw_settings )
class ZoneTransaction ( FirewallTransaction ) :
"""
ZoneTransaction
"""
def __init__ ( self , fw , action_args = None , zone = None , desired_state = None ,
permanent = True , immediate = False , fw_offline = False ,
enabled_values = None , disabled_values = None ) :
super ( ZoneTransaction , self ) . __init__ (
fw , action_args = action_args , desired_state = desired_state , zone = zone ,
permanent = permanent , immediate = immediate , fw_offline = fw_offline ,
enabled_values = enabled_values or [ " present " ] ,
disabled_values = disabled_values or [ " absent " ] )
self . enabled_msg = " Added zone %s " % \
( self . zone )
self . disabled_msg = " Removed zone %s " % \
( self . zone )
self . tx_not_permanent_error_msg = " Zone operations must be permanent. " \
" Make sure you didn ' t set the ' permanent ' flag to ' false ' or the ' immediate ' flag to ' true ' . "
def get_enabled_immediate ( self ) :
module . fail_json ( msg = self . tx_not_permanent_error_msg )
def get_enabled_permanent ( self ) :
if self . zone in fw . config ( ) . getZoneNames ( ) :
return True
else :
return False
def set_enabled_immediate ( self ) :
module . fail_json ( msg = self . tx_not_permanent_error_msg )
def set_enabled_permanent ( self ) :
fw . config ( ) . addZone ( self . zone , FirewallClientZoneSettings ( ) )
def set_disabled_immediate ( self ) :
module . fail_json ( msg = self . tx_not_permanent_error_msg )
def set_disabled_permanent ( self ) :
zone_obj = self . fw . config ( ) . getZoneByName ( self . zone )
zone_obj . remove ( )
def main ( ) :
global module
@ -740,7 +799,7 @@ def main():
immediate = dict ( type = ' bool ' , default = False ) ,
source = dict ( required = False , default = None ) ,
permanent = dict ( type = ' bool ' , required = False , default = None ) ,
state = dict ( choices = [ ' enabled ' , ' disabled ' ], required = True ) ,
state = dict ( choices = [ ' enabled ' , ' disabled ' , ' present ' , ' absent ' ], required = True ) ,
timeout = dict ( type = ' int ' , required = False , default = 0 ) ,
interface = dict ( required = False , default = None ) ,
masquerade = dict ( required = False , default = None ) ,
@ -825,6 +884,10 @@ def main():
module . fail_json (
msg = ' can only operate on port, service, rich_rule, or interface at once '
)
elif modification_count > 0 and desired_state in [ ' absent ' , ' present ' ] :
module . fail_json (
msg = ' absent and present state can only be used in zone level operations '
)
if service is not None :
@ -926,6 +989,24 @@ def main():
changed , transaction_msgs = transaction . run ( )
msgs = msgs + transaction_msgs
''' If there are no changes within the zone we are operating on the zone itself '''
if modification_count == 0 and desired_state in [ ' absent ' , ' present ' ] :
transaction = ZoneTransaction (
fw ,
action_args = ( ) ,
zone = zone ,
desired_state = desired_state ,
permanent = permanent ,
immediate = immediate ,
fw_offline = fw_offline
)
changed , transaction_msgs = transaction . run ( )
msgs = msgs + transaction_msgs
if changed is True :
msgs . append ( " Changed zone %s to %s " % ( zone , desired_state ) )
if fw_offline :
msgs . append ( " (offline operation: only on-disk configs were altered) " )