mirror of https://github.com/ansible/ansible.git
Migrated to fortinet.fortios
parent
a73c1da43a
commit
74c95055e9
@ -1,288 +0,0 @@
|
||||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
#
|
||||
# (c) 2017 Fortinet, Inc
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
# BEGIN STATIC DATA / MESSAGES
|
||||
class FMGRMethods:
|
||||
GET = "get"
|
||||
SET = "set"
|
||||
EXEC = "exec"
|
||||
EXECUTE = "exec"
|
||||
UPDATE = "update"
|
||||
ADD = "add"
|
||||
DELETE = "delete"
|
||||
REPLACE = "replace"
|
||||
CLONE = "clone"
|
||||
MOVE = "move"
|
||||
|
||||
|
||||
BASE_HEADERS = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
|
||||
|
||||
# FMGR RETURN CODES
|
||||
FMGR_RC = {
|
||||
"fmgr_return_codes": {
|
||||
0: {
|
||||
"msg": "OK",
|
||||
"changed": True,
|
||||
"stop_on_success": True
|
||||
},
|
||||
-100000: {
|
||||
"msg": "Module returned without actually running anything. "
|
||||
"Check parameters, and please contact the authors if needed.",
|
||||
"failed": True
|
||||
},
|
||||
-2: {
|
||||
"msg": "Object already exists.",
|
||||
"skipped": True,
|
||||
"changed": False,
|
||||
"good_codes": [0, -2]
|
||||
},
|
||||
-6: {
|
||||
"msg": "Invalid Url. Sometimes this can happen because the path is mapped to a hostname or object that"
|
||||
" doesn't exist. Double check your input object parameters."
|
||||
},
|
||||
-3: {
|
||||
"msg": "Object doesn't exist.",
|
||||
"skipped": True,
|
||||
"changed": False,
|
||||
"good_codes": [0, -3]
|
||||
},
|
||||
-10131: {
|
||||
"msg": "Object dependency failed. Do all named objects in parameters exist?",
|
||||
"changed": False,
|
||||
"skipped": True
|
||||
},
|
||||
-9998: {
|
||||
"msg": "Duplicate object. Try using mode='set', if using add. STOPPING. Use 'ignore_errors=yes' in playbook"
|
||||
"to override and mark successful.",
|
||||
},
|
||||
-20042: {
|
||||
"msg": "Device Unreachable.",
|
||||
"skipped": True
|
||||
},
|
||||
-10033: {
|
||||
"msg": "Duplicate object. Try using mode='set', if using add.",
|
||||
"changed": False,
|
||||
"skipped": True
|
||||
},
|
||||
-10000: {
|
||||
"msg": "Duplicate object. Try using mode='set', if using add.",
|
||||
"changed": False,
|
||||
"skipped": True
|
||||
},
|
||||
-20010: {
|
||||
"msg": "Device already added to FortiManager. Serial number already in use.",
|
||||
"good_codes": [0, -20010],
|
||||
"changed": False,
|
||||
"stop_on_success": True
|
||||
},
|
||||
-20002: {
|
||||
"msg": "Invalid Argument -- Does this Device exist on FortiManager?",
|
||||
"changed": False,
|
||||
"skipped": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEFAULT_RESULT_OBJ = (-100000, {"msg": "Nothing Happened. Check that handle_response is being called!"})
|
||||
FAIL_SOCKET_MSG = {"msg": "Socket Path Empty! The persistent connection manager is messed up. "
|
||||
"Try again in a few moments."}
|
||||
|
||||
|
||||
# BEGIN ERROR EXCEPTIONS
|
||||
class FMGBaseException(Exception):
|
||||
"""Wrapper to catch the unexpected"""
|
||||
|
||||
def __init__(self, msg=None, *args, **kwargs):
|
||||
if msg is None:
|
||||
msg = "An exception occurred within the fortimanager.py httpapi connection plugin."
|
||||
super(FMGBaseException, self).__init__(msg, *args)
|
||||
|
||||
# END ERROR CLASSES
|
||||
|
||||
|
||||
# BEGIN CLASSES
|
||||
class FMGRCommon(object):
|
||||
|
||||
@staticmethod
|
||||
def format_request(method, url, *args, **kwargs):
|
||||
"""
|
||||
Formats the payload from the module, into a payload the API handler can use.
|
||||
|
||||
:param url: Connection URL to access
|
||||
:type url: string
|
||||
:param method: The preferred API Request method (GET, ADD, POST, etc....)
|
||||
:type method: basestring
|
||||
:param kwargs: The payload dictionary from the module to be converted.
|
||||
|
||||
:return: Properly formatted dictionary payload for API Request via Connection Plugin.
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
params = [{"url": url}]
|
||||
if args:
|
||||
for arg in args:
|
||||
params[0].update(arg)
|
||||
if kwargs:
|
||||
keylist = list(kwargs)
|
||||
for k in keylist:
|
||||
kwargs[k.replace("__", "-")] = kwargs.pop(k)
|
||||
if method == "get" or method == "clone":
|
||||
params[0].update(kwargs)
|
||||
else:
|
||||
if kwargs.get("data", False):
|
||||
params[0]["data"] = kwargs["data"]
|
||||
else:
|
||||
params[0]["data"] = kwargs
|
||||
return params
|
||||
|
||||
@staticmethod
|
||||
def split_comma_strings_into_lists(obj):
|
||||
"""
|
||||
Splits a CSV String into a list. Also takes a dictionary, and converts any CSV strings in any key, to a list.
|
||||
|
||||
:param obj: object in CSV format to be parsed.
|
||||
:type obj: str or dict
|
||||
|
||||
:return: A list containing the CSV items.
|
||||
:rtype: list
|
||||
"""
|
||||
return_obj = ()
|
||||
if isinstance(obj, dict):
|
||||
if len(obj) > 0:
|
||||
for k, v in obj.items():
|
||||
if isinstance(v, str):
|
||||
new_list = list()
|
||||
if "," in v:
|
||||
new_items = v.split(",")
|
||||
for item in new_items:
|
||||
new_list.append(item.strip())
|
||||
obj[k] = new_list
|
||||
return_obj = obj
|
||||
elif isinstance(obj, str):
|
||||
return_obj = obj.replace(" ", "").split(",")
|
||||
|
||||
return return_obj
|
||||
|
||||
@staticmethod
|
||||
def cidr_to_netmask(cidr):
|
||||
"""
|
||||
Converts a CIDR Network string to full blown IP/Subnet format in decimal format.
|
||||
Decided not use IP Address module to keep includes to a minimum.
|
||||
|
||||
:param cidr: String object in CIDR format to be processed
|
||||
:type cidr: str
|
||||
|
||||
:return: A string object that looks like this "x.x.x.x/y.y.y.y"
|
||||
:rtype: str
|
||||
"""
|
||||
if isinstance(cidr, str):
|
||||
cidr = int(cidr)
|
||||
mask = (0xffffffff >> (32 - cidr)) << (32 - cidr)
|
||||
return (str((0xff000000 & mask) >> 24) + '.'
|
||||
+ str((0x00ff0000 & mask) >> 16) + '.'
|
||||
+ str((0x0000ff00 & mask) >> 8) + '.'
|
||||
+ str((0x000000ff & mask)))
|
||||
|
||||
@staticmethod
|
||||
def paramgram_child_list_override(list_overrides, paramgram, module):
|
||||
"""
|
||||
If a list of items was provided to a "parent" paramgram attribute, the paramgram needs to be rewritten.
|
||||
The child keys of the desired attribute need to be deleted, and then that "parent" keys' contents is replaced
|
||||
With the list of items that was provided.
|
||||
|
||||
:param list_overrides: Contains the response from the FortiManager.
|
||||
:type list_overrides: list
|
||||
:param paramgram: Contains the paramgram passed to the modules' local modify function.
|
||||
:type paramgram: dict
|
||||
:param module: Contains the Ansible Module Object being used by the module.
|
||||
:type module: classObject
|
||||
|
||||
:return: A new "paramgram" refactored to allow for multiple entries being added.
|
||||
:rtype: dict
|
||||
"""
|
||||
if len(list_overrides) > 0:
|
||||
for list_variable in list_overrides:
|
||||
try:
|
||||
list_variable = list_variable.replace("-", "_")
|
||||
override_data = module.params[list_variable]
|
||||
if override_data:
|
||||
del paramgram[list_variable]
|
||||
paramgram[list_variable] = override_data
|
||||
except BaseException as e:
|
||||
raise FMGBaseException("Error occurred merging custom lists for the paramgram parent: " + str(e))
|
||||
return paramgram
|
||||
|
||||
@staticmethod
|
||||
def syslog(module, msg):
|
||||
try:
|
||||
module.log(msg=msg)
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
|
||||
# RECURSIVE FUNCTIONS START
|
||||
def prepare_dict(obj):
|
||||
"""
|
||||
Removes any keys from a dictionary that are only specific to our use in the module. FortiManager will reject
|
||||
requests with these empty/None keys in it.
|
||||
|
||||
:param obj: Dictionary object to be processed.
|
||||
:type obj: dict
|
||||
|
||||
:return: Processed dictionary.
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
list_of_elems = ["mode", "adom", "host", "username", "password"]
|
||||
|
||||
if isinstance(obj, dict):
|
||||
obj = dict((key, prepare_dict(value)) for (key, value) in obj.items() if key not in list_of_elems)
|
||||
return obj
|
||||
|
||||
|
||||
def scrub_dict(obj):
|
||||
"""
|
||||
Removes any keys from a dictionary that are EMPTY -- this includes parent keys. FortiManager doesn't
|
||||
like empty keys in dictionaries
|
||||
|
||||
:param obj: Dictionary object to be processed.
|
||||
:type obj: dict
|
||||
|
||||
:return: Processed dictionary.
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
if isinstance(obj, dict):
|
||||
return dict((k, scrub_dict(v)) for k, v in obj.items() if v and scrub_dict(v))
|
||||
else:
|
||||
return obj
|
||||
@ -1,466 +0,0 @@
|
||||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
#
|
||||
# (c) 2017 Fortinet, Inc
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
from ansible.module_utils.network.fortimanager.common import FMGR_RC
|
||||
from ansible.module_utils.network.fortimanager.common import FMGBaseException
|
||||
from ansible.module_utils.network.fortimanager.common import FMGRCommon
|
||||
from ansible.module_utils.network.fortimanager.common import scrub_dict
|
||||
|
||||
# check for pyFMG lib - DEPRECATING
|
||||
try:
|
||||
from pyFMG.fortimgr import FortiManager
|
||||
HAS_PYFMGR = True
|
||||
except ImportError:
|
||||
HAS_PYFMGR = False
|
||||
|
||||
# ACTIVE BUG WITH OUR DEBUG IMPORT CALL -- BECAUSE IT'S UNDER MODULE_UTILITIES
|
||||
# WHEN module_common.recursive_finder() runs under the module loader, it looks for this namespace debug import
|
||||
# and because it's not there, it always fails, regardless of it being under a try/catch here.
|
||||
# we're going to move it to a different namespace.
|
||||
# # check for debug lib
|
||||
# try:
|
||||
# from ansible.module_utils.network.fortimanager.fortimanager_debug import debug_dump
|
||||
# HAS_FMGR_DEBUG = True
|
||||
# except:
|
||||
# HAS_FMGR_DEBUG = False
|
||||
|
||||
|
||||
# BEGIN HANDLER CLASSES
|
||||
class FortiManagerHandler(object):
|
||||
def __init__(self, conn, module):
|
||||
self._conn = conn
|
||||
self._module = module
|
||||
self._tools = FMGRCommon
|
||||
|
||||
def process_request(self, url, datagram, method):
|
||||
"""
|
||||
Formats and Runs the API Request via Connection Plugin. Streamlined for use FROM Modules.
|
||||
|
||||
:param url: Connection URL to access
|
||||
:type url: string
|
||||
:param datagram: The prepared payload for the API Request in dictionary format
|
||||
:type datagram: dict
|
||||
:param method: The preferred API Request method (GET, ADD, POST, etc....)
|
||||
:type method: basestring
|
||||
|
||||
:return: Dictionary containing results of the API Request via Connection Plugin
|
||||
:rtype: dict
|
||||
"""
|
||||
data = self._tools.format_request(method, url, **datagram)
|
||||
response = self._conn.send_request(method, data)
|
||||
|
||||
# if HAS_FMGR_DEBUG:
|
||||
# try:
|
||||
# debug_dump(response, datagram, self._module.paramgram, url, method)
|
||||
# except BaseException:
|
||||
# pass
|
||||
|
||||
return response
|
||||
|
||||
def govern_response(self, module, results, msg=None, good_codes=None,
|
||||
stop_on_fail=None, stop_on_success=None, skipped=None,
|
||||
changed=None, unreachable=None, failed=None, success=None, changed_if_success=None,
|
||||
ansible_facts=None):
|
||||
"""
|
||||
This function will attempt to apply default values to canned responses from FortiManager we know of.
|
||||
This saves time, and turns the response in the module into a "one-liner", while still giving us...
|
||||
the flexibility to directly use return_response in modules if we have too. This function saves repeated code.
|
||||
|
||||
:param module: The Ansible Module CLASS object, used to run fail/exit json
|
||||
:type module: object
|
||||
:param msg: An overridable custom message from the module that called this.
|
||||
:type msg: string
|
||||
:param results: A dictionary object containing an API call results
|
||||
:type results: dict
|
||||
:param good_codes: A list of exit codes considered successful from FortiManager
|
||||
:type good_codes: list
|
||||
:param stop_on_fail: If true, stops playbook run when return code is NOT IN good codes (default: true)
|
||||
:type stop_on_fail: boolean
|
||||
:param stop_on_success: If true, stops playbook run when return code is IN good codes (default: false)
|
||||
:type stop_on_success: boolean
|
||||
:param changed: If True, tells Ansible that object was changed (default: false)
|
||||
:type skipped: boolean
|
||||
:param skipped: If True, tells Ansible that object was skipped (default: false)
|
||||
:type skipped: boolean
|
||||
:param unreachable: If True, tells Ansible that object was unreachable (default: false)
|
||||
:type unreachable: boolean
|
||||
:param failed: If True, tells Ansible that execution was a failure. Overrides good_codes. (default: false)
|
||||
:type unreachable: boolean
|
||||
:param success: If True, tells Ansible that execution was a success. Overrides good_codes. (default: false)
|
||||
:type unreachable: boolean
|
||||
:param changed_if_success: If True, defaults to changed if successful if you specify or not"
|
||||
:type changed_if_success: boolean
|
||||
:param ansible_facts: A prepared dictionary of ansible facts from the execution.
|
||||
:type ansible_facts: dict
|
||||
"""
|
||||
if module is None and results is None:
|
||||
raise FMGBaseException("govern_response() was called without a module and/or results tuple! Fix!")
|
||||
# Get the Return code from results
|
||||
try:
|
||||
rc = results[0]
|
||||
except BaseException:
|
||||
raise FMGBaseException("govern_response() was called without the return code at results[0]")
|
||||
|
||||
# init a few items
|
||||
rc_data = None
|
||||
|
||||
# Get the default values for the said return code.
|
||||
try:
|
||||
rc_codes = FMGR_RC.get('fmgr_return_codes')
|
||||
rc_data = rc_codes.get(rc)
|
||||
except BaseException:
|
||||
pass
|
||||
|
||||
if not rc_data:
|
||||
rc_data = {}
|
||||
# ONLY add to overrides if not none -- This is very important that the keys aren't added at this stage
|
||||
# if they are empty. And there aren't that many, so let's just do a few if then statements.
|
||||
if good_codes is not None:
|
||||
rc_data["good_codes"] = good_codes
|
||||
if stop_on_fail is not None:
|
||||
rc_data["stop_on_fail"] = stop_on_fail
|
||||
if stop_on_success is not None:
|
||||
rc_data["stop_on_success"] = stop_on_success
|
||||
if skipped is not None:
|
||||
rc_data["skipped"] = skipped
|
||||
if changed is not None:
|
||||
rc_data["changed"] = changed
|
||||
if unreachable is not None:
|
||||
rc_data["unreachable"] = unreachable
|
||||
if failed is not None:
|
||||
rc_data["failed"] = failed
|
||||
if success is not None:
|
||||
rc_data["success"] = success
|
||||
if changed_if_success is not None:
|
||||
rc_data["changed_if_success"] = changed_if_success
|
||||
if results is not None:
|
||||
rc_data["results"] = results
|
||||
if msg is not None:
|
||||
rc_data["msg"] = msg
|
||||
if ansible_facts is None:
|
||||
rc_data["ansible_facts"] = {}
|
||||
else:
|
||||
rc_data["ansible_facts"] = ansible_facts
|
||||
|
||||
return self.return_response(module=module,
|
||||
results=results,
|
||||
msg=rc_data.get("msg", "NULL"),
|
||||
good_codes=rc_data.get("good_codes", (0,)),
|
||||
stop_on_fail=rc_data.get("stop_on_fail", True),
|
||||
stop_on_success=rc_data.get("stop_on_success", False),
|
||||
skipped=rc_data.get("skipped", False),
|
||||
changed=rc_data.get("changed", False),
|
||||
changed_if_success=rc_data.get("changed_if_success", False),
|
||||
unreachable=rc_data.get("unreachable", False),
|
||||
failed=rc_data.get("failed", False),
|
||||
success=rc_data.get("success", False),
|
||||
ansible_facts=rc_data.get("ansible_facts", dict()))
|
||||
|
||||
@staticmethod
|
||||
def return_response(module, results, msg="NULL", good_codes=(0,),
|
||||
stop_on_fail=True, stop_on_success=False, skipped=False,
|
||||
changed=False, unreachable=False, failed=False, success=False, changed_if_success=True,
|
||||
ansible_facts=()):
|
||||
"""
|
||||
This function controls the logout and error reporting after an method or function runs. The exit_json for
|
||||
ansible comes from logic within this function. If this function returns just the msg, it means to continue
|
||||
execution on the playbook. It is called from the ansible module, or from the self.govern_response function.
|
||||
|
||||
:param module: The Ansible Module CLASS object, used to run fail/exit json
|
||||
:type module: object
|
||||
:param msg: An overridable custom message from the module that called this.
|
||||
:type msg: string
|
||||
:param results: A dictionary object containing an API call results
|
||||
:type results: dict
|
||||
:param good_codes: A list of exit codes considered successful from FortiManager
|
||||
:type good_codes: list
|
||||
:param stop_on_fail: If true, stops playbook run when return code is NOT IN good codes (default: true)
|
||||
:type stop_on_fail: boolean
|
||||
:param stop_on_success: If true, stops playbook run when return code is IN good codes (default: false)
|
||||
:type stop_on_success: boolean
|
||||
:param changed: If True, tells Ansible that object was changed (default: false)
|
||||
:type skipped: boolean
|
||||
:param skipped: If True, tells Ansible that object was skipped (default: false)
|
||||
:type skipped: boolean
|
||||
:param unreachable: If True, tells Ansible that object was unreachable (default: false)
|
||||
:type unreachable: boolean
|
||||
:param failed: If True, tells Ansible that execution was a failure. Overrides good_codes. (default: false)
|
||||
:type unreachable: boolean
|
||||
:param success: If True, tells Ansible that execution was a success. Overrides good_codes. (default: false)
|
||||
:type unreachable: boolean
|
||||
:param changed_if_success: If True, defaults to changed if successful if you specify or not"
|
||||
:type changed_if_success: boolean
|
||||
:param ansible_facts: A prepared dictionary of ansible facts from the execution.
|
||||
:type ansible_facts: dict
|
||||
|
||||
:return: A string object that contains an error message
|
||||
:rtype: str
|
||||
"""
|
||||
|
||||
# VALIDATION ERROR
|
||||
if (len(results) == 0) or (failed and success) or (changed and unreachable):
|
||||
module.exit_json(msg="Handle_response was called with no results, or conflicting failed/success or "
|
||||
"changed/unreachable parameters. Fix the exit code on module. "
|
||||
"Generic Failure", failed=True)
|
||||
|
||||
# IDENTIFY SUCCESS/FAIL IF NOT DEFINED
|
||||
if not failed and not success:
|
||||
if len(results) > 0:
|
||||
if results[0] not in good_codes:
|
||||
failed = True
|
||||
elif results[0] in good_codes:
|
||||
success = True
|
||||
|
||||
if len(results) > 0:
|
||||
# IF NO MESSAGE WAS SUPPLIED, GET IT FROM THE RESULTS, IF THAT DOESN'T WORK, THEN WRITE AN ERROR MESSAGE
|
||||
if msg == "NULL":
|
||||
try:
|
||||
msg = results[1]['status']['message']
|
||||
except BaseException:
|
||||
msg = "No status message returned at results[1][status][message], " \
|
||||
"and none supplied to msg parameter for handle_response."
|
||||
|
||||
if failed:
|
||||
# BECAUSE SKIPPED/FAILED WILL OFTEN OCCUR ON CODES THAT DON'T GET INCLUDED, THEY ARE CONSIDERED FAILURES
|
||||
# HOWEVER, THEY ARE MUTUALLY EXCLUSIVE, SO IF IT IS MARKED SKIPPED OR UNREACHABLE BY THE MODULE LOGIC
|
||||
# THEN REMOVE THE FAILED FLAG SO IT DOESN'T OVERRIDE THE DESIRED STATUS OF SKIPPED OR UNREACHABLE.
|
||||
if failed and skipped:
|
||||
failed = False
|
||||
if failed and unreachable:
|
||||
failed = False
|
||||
if stop_on_fail:
|
||||
module.exit_json(msg=msg, failed=failed, changed=changed, unreachable=unreachable, skipped=skipped,
|
||||
results=results[1], ansible_facts=ansible_facts, rc=results[0],
|
||||
invocation={"module_args": ansible_facts["ansible_params"]})
|
||||
elif success:
|
||||
if changed_if_success:
|
||||
changed = True
|
||||
success = False
|
||||
if stop_on_success:
|
||||
module.exit_json(msg=msg, success=success, changed=changed, unreachable=unreachable,
|
||||
skipped=skipped, results=results[1], ansible_facts=ansible_facts, rc=results[0],
|
||||
invocation={"module_args": ansible_facts["ansible_params"]})
|
||||
return msg
|
||||
|
||||
def construct_ansible_facts(self, response, ansible_params, paramgram, *args, **kwargs):
|
||||
"""
|
||||
Constructs a dictionary to return to ansible facts, containing various information about the execution.
|
||||
|
||||
:param response: Contains the response from the FortiManager.
|
||||
:type response: dict
|
||||
:param ansible_params: Contains the parameters Ansible was called with.
|
||||
:type ansible_params: dict
|
||||
:param paramgram: Contains the paramgram passed to the modules' local modify function.
|
||||
:type paramgram: dict
|
||||
:param args: Free-form arguments that could be added.
|
||||
:param kwargs: Free-form keyword arguments that could be added.
|
||||
|
||||
:return: A dictionary containing lots of information to append to Ansible Facts.
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
facts = {
|
||||
"response": response,
|
||||
"ansible_params": scrub_dict(ansible_params),
|
||||
"paramgram": scrub_dict(paramgram),
|
||||
"connected_fmgr": self._conn.return_connected_fmgr()
|
||||
}
|
||||
|
||||
if args:
|
||||
facts["custom_args"] = args
|
||||
if kwargs:
|
||||
facts.update(kwargs)
|
||||
|
||||
return facts
|
||||
|
||||
|
||||
##########################
|
||||
# BEGIN DEPRECATED METHODS
|
||||
##########################
|
||||
|
||||
# SOME OF THIS CODE IS DUPLICATED IN THE PLUGIN, BUT THOSE ARE PLUGIN SPECIFIC. THIS VERSION STILL ALLOWS FOR
|
||||
# THE USAGE OF PYFMG FOR CUSTOMERS WHO HAVE NOT YET UPGRADED TO ANSIBLE 2.7
|
||||
|
||||
# LEGACY PYFMG METHODS START
|
||||
# USED TO DETERMINE LOCK CONTEXT ON A FORTIMANAGER. A DATABASE LOCKING CONCEPT THAT NEEDS TO BE ACCOUNTED FOR.
|
||||
|
||||
class FMGLockContext(object):
|
||||
"""
|
||||
- DEPRECATING: USING CONNECTION MANAGER NOW INSTEAD. EVENTUALLY THIS CLASS WILL DISAPPEAR. PLEASE
|
||||
- CONVERT ALL MODULES TO CONNECTION MANAGER METHOD.
|
||||
- LEGACY pyFMG HANDLER OBJECT: REQUIRES A CHECK FOR PY FMG AT TOP OF PAGE
|
||||
"""
|
||||
def __init__(self, fmg):
|
||||
self._fmg = fmg
|
||||
self._locked_adom_list = list()
|
||||
self._uses_workspace = False
|
||||
self._uses_adoms = False
|
||||
|
||||
@property
|
||||
def uses_workspace(self):
|
||||
return self._uses_workspace
|
||||
|
||||
@uses_workspace.setter
|
||||
def uses_workspace(self, val):
|
||||
self._uses_workspace = val
|
||||
|
||||
@property
|
||||
def uses_adoms(self):
|
||||
return self._uses_adoms
|
||||
|
||||
@uses_adoms.setter
|
||||
def uses_adoms(self, val):
|
||||
self._uses_adoms = val
|
||||
|
||||
def add_adom_to_lock_list(self, adom):
|
||||
if adom not in self._locked_adom_list:
|
||||
self._locked_adom_list.append(adom)
|
||||
|
||||
def remove_adom_from_lock_list(self, adom):
|
||||
if adom in self._locked_adom_list:
|
||||
self._locked_adom_list.remove(adom)
|
||||
|
||||
def check_mode(self):
|
||||
url = "/cli/global/system/global"
|
||||
code, resp_obj = self._fmg.get(url, fields=["workspace-mode", "adom-status"])
|
||||
try:
|
||||
if resp_obj["workspace-mode"] != 0:
|
||||
self.uses_workspace = True
|
||||
except KeyError:
|
||||
self.uses_workspace = False
|
||||
try:
|
||||
if resp_obj["adom-status"] == 1:
|
||||
self.uses_adoms = True
|
||||
except KeyError:
|
||||
self.uses_adoms = False
|
||||
|
||||
def run_unlock(self):
|
||||
for adom_locked in self._locked_adom_list:
|
||||
self.unlock_adom(adom_locked)
|
||||
|
||||
def lock_adom(self, adom=None, *args, **kwargs):
|
||||
if adom:
|
||||
if adom.lower() == "global":
|
||||
url = "/dvmdb/global/workspace/lock/"
|
||||
else:
|
||||
url = "/dvmdb/adom/{adom}/workspace/lock/".format(adom=adom)
|
||||
else:
|
||||
url = "/dvmdb/adom/root/workspace/lock"
|
||||
code, respobj = self._fmg.execute(url, {}, *args, **kwargs)
|
||||
if code == 0 and respobj["status"]["message"].lower() == "ok":
|
||||
self.add_adom_to_lock_list(adom)
|
||||
return code, respobj
|
||||
|
||||
def unlock_adom(self, adom=None, *args, **kwargs):
|
||||
if adom:
|
||||
if adom.lower() == "global":
|
||||
url = "/dvmdb/global/workspace/unlock/"
|
||||
else:
|
||||
url = "/dvmdb/adom/{adom}/workspace/unlock/".format(adom=adom)
|
||||
else:
|
||||
url = "/dvmdb/adom/root/workspace/unlock"
|
||||
code, respobj = self._fmg.execute(url, {}, *args, **kwargs)
|
||||
if code == 0 and respobj["status"]["message"].lower() == "ok":
|
||||
self.remove_adom_from_lock_list(adom)
|
||||
return code, respobj
|
||||
|
||||
def commit_changes(self, adom=None, aux=False, *args, **kwargs):
|
||||
if adom:
|
||||
if aux:
|
||||
url = "/pm/config/adom/{adom}/workspace/commit".format(adom=adom)
|
||||
else:
|
||||
if adom.lower() == "global":
|
||||
url = "/dvmdb/global/workspace/commit/"
|
||||
else:
|
||||
url = "/dvmdb/adom/{adom}/workspace/commit".format(adom=adom)
|
||||
else:
|
||||
url = "/dvmdb/adom/root/workspace/commit"
|
||||
return self._fmg.execute(url, {}, *args, **kwargs)
|
||||
|
||||
|
||||
# DEPRECATED -- USE PLUGIN INSTEAD
|
||||
class AnsibleFortiManager(object):
|
||||
"""
|
||||
- DEPRECATING: USING CONNECTION MANAGER NOW INSTEAD. EVENTUALLY THIS CLASS WILL DISAPPEAR. PLEASE
|
||||
- CONVERT ALL MODULES TO CONNECTION MANAGER METHOD.
|
||||
- LEGACY pyFMG HANDLER OBJECT: REQUIRES A CHECK FOR PY FMG AT TOP OF PAGE
|
||||
"""
|
||||
|
||||
def __init__(self, module, ip=None, username=None, passwd=None, use_ssl=True, verify_ssl=False, timeout=300):
|
||||
self.ip = ip
|
||||
self.username = username
|
||||
self.passwd = passwd
|
||||
self.use_ssl = use_ssl
|
||||
self.verify_ssl = verify_ssl
|
||||
self.timeout = timeout
|
||||
self.fmgr_instance = None
|
||||
|
||||
if not HAS_PYFMGR:
|
||||
module.fail_json(msg='Could not import the python library pyFMG required by this module')
|
||||
|
||||
self.module = module
|
||||
|
||||
def login(self):
|
||||
if self.ip is not None:
|
||||
self.fmgr_instance = FortiManager(self.ip, self.username, self.passwd, use_ssl=self.use_ssl,
|
||||
verify_ssl=self.verify_ssl, timeout=self.timeout, debug=False,
|
||||
disable_request_warnings=True)
|
||||
return self.fmgr_instance.login()
|
||||
|
||||
def logout(self):
|
||||
if self.fmgr_instance.sid is not None:
|
||||
self.fmgr_instance.logout()
|
||||
|
||||
def get(self, url, data):
|
||||
return self.fmgr_instance.get(url, **data)
|
||||
|
||||
def set(self, url, data):
|
||||
return self.fmgr_instance.set(url, **data)
|
||||
|
||||
def update(self, url, data):
|
||||
return self.fmgr_instance.update(url, **data)
|
||||
|
||||
def delete(self, url, data):
|
||||
return self.fmgr_instance.delete(url, **data)
|
||||
|
||||
def add(self, url, data):
|
||||
return self.fmgr_instance.add(url, **data)
|
||||
|
||||
def execute(self, url, data):
|
||||
return self.fmgr_instance.execute(url, **data)
|
||||
|
||||
def move(self, url, data):
|
||||
return self.fmgr_instance.move(url, **data)
|
||||
|
||||
def clone(self, url, data):
|
||||
return self.fmgr_instance.clone(url, **data)
|
||||
|
||||
##########################
|
||||
# END DEPRECATED METHODS
|
||||
##########################
|
||||
@ -1,45 +0,0 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
"""
|
||||
The arg spec for the fortios monitor module.
|
||||
"""
|
||||
|
||||
|
||||
class FactsArgs(object):
|
||||
""" The arg spec for the fortios monitor module
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
pass
|
||||
|
||||
argument_spec = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": False},
|
||||
"gather_subset": {
|
||||
"required": True, "type": "list", "elements": "dict",
|
||||
"options": {
|
||||
"fact": {"required": True, "type": "str"},
|
||||
"filters": {"required": False, "type": "list", "elements": "dict"}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
# GNU General Public License v3.0+
|
||||
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
"""
|
||||
The arg spec for the fortios_facts module
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
class SystemArgs(object):
|
||||
"""The arg spec for the fortios_facts module
|
||||
"""
|
||||
|
||||
FACT_SYSTEM_SUBSETS = frozenset([
|
||||
'system_current-admins_select',
|
||||
'system_firmware_select',
|
||||
'system_fortimanager_status',
|
||||
'system_ha-checksums_select',
|
||||
'system_interface_select',
|
||||
'system_status_select',
|
||||
'system_time_select',
|
||||
])
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
pass
|
||||
@ -1,92 +0,0 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
"""
|
||||
The facts class for fortios
|
||||
this file validates each subset of monitor and selectively
|
||||
calls the appropriate facts gathering and monitoring function
|
||||
"""
|
||||
|
||||
from ansible.module_utils.network.fortios.argspec.facts.facts import FactsArgs
|
||||
from ansible.module_utils.network.fortios.argspec.system.system import SystemArgs
|
||||
from ansible.module_utils.network.common.facts.facts import FactsBase
|
||||
from ansible.module_utils.network.fortios.facts.system.system import SystemFacts
|
||||
|
||||
|
||||
class Facts(FactsBase):
|
||||
""" The facts class for fortios
|
||||
"""
|
||||
|
||||
FACT_SUBSETS = {
|
||||
"system": SystemFacts
|
||||
}
|
||||
|
||||
def __init__(self, module, fos=None, subset=None):
|
||||
super(Facts, self).__init__(module)
|
||||
self._fos = fos
|
||||
self._subset = subset
|
||||
|
||||
def gen_runable(self, subsets, valid_subsets):
|
||||
""" Generate the runable subset
|
||||
|
||||
:param module: The module instance
|
||||
:param subsets: The provided subsets
|
||||
:param valid_subsets: The valid subsets
|
||||
:rtype: list
|
||||
:returns: The runable subsets
|
||||
"""
|
||||
runable_subsets = []
|
||||
FACT_DETAIL_SUBSETS = []
|
||||
FACT_DETAIL_SUBSETS.extend(SystemArgs.FACT_SYSTEM_SUBSETS)
|
||||
|
||||
for subset in subsets:
|
||||
if subset['fact'] not in FACT_DETAIL_SUBSETS:
|
||||
self._module.fail_json(msg='Subset must be one of [%s], got %s' %
|
||||
(', '.join(sorted([item for item in FACT_DETAIL_SUBSETS])), subset['fact']))
|
||||
|
||||
for valid_subset in frozenset(self.FACT_SUBSETS.keys()):
|
||||
if subset['fact'].startswith(valid_subset):
|
||||
runable_subsets.append((subset, valid_subset))
|
||||
|
||||
return runable_subsets
|
||||
|
||||
def get_network_legacy_facts(self, fact_legacy_obj_map, legacy_facts_type=None):
|
||||
if not legacy_facts_type:
|
||||
legacy_facts_type = self._gather_subset
|
||||
|
||||
runable_subsets = self.gen_runable(legacy_facts_type, frozenset(fact_legacy_obj_map.keys()))
|
||||
if runable_subsets:
|
||||
self.ansible_facts['ansible_net_gather_subset'] = []
|
||||
|
||||
instances = list()
|
||||
for (subset, valid_subset) in runable_subsets:
|
||||
instances.append(fact_legacy_obj_map[valid_subset](self._module, self._fos, subset))
|
||||
|
||||
for inst in instances:
|
||||
inst.populate_facts(self._connection, self.ansible_facts)
|
||||
|
||||
def get_facts(self, facts_type=None, data=None):
|
||||
""" Collect the facts for fortios
|
||||
:param facts_type: List of facts types
|
||||
:param data: previously collected conf
|
||||
:rtype: dict
|
||||
:return: the facts gathered
|
||||
"""
|
||||
self.get_network_legacy_facts(self.FACT_SUBSETS, facts_type)
|
||||
|
||||
return self.ansible_facts, self._warnings
|
||||
@ -1,63 +0,0 @@
|
||||
#
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
# GNU General Public License v3.0+
|
||||
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
"""
|
||||
The fortios system facts class
|
||||
It is in this file the runtime information is collected from the device
|
||||
for a given resource, parsed, and the facts tree is populated
|
||||
based on the configuration.
|
||||
"""
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
import re
|
||||
from ansible.module_utils.network.common import utils
|
||||
from ansible.module_utils.network.fortios.argspec.system.system import SystemArgs
|
||||
|
||||
|
||||
class SystemFacts(object):
|
||||
""" The fortios system facts class
|
||||
"""
|
||||
|
||||
def __init__(self, module, fos=None, subset=None, subspec='config', options='options'):
|
||||
self._module = module
|
||||
self._fos = fos
|
||||
self._subset = subset
|
||||
|
||||
def populate_facts(self, connection, ansible_facts, data=None):
|
||||
""" Populate the facts for system
|
||||
:param connection: the device connection
|
||||
:param ansible_facts: Facts dictionary
|
||||
:rtype: dictionary
|
||||
:returns: facts
|
||||
"""
|
||||
ansible_facts['ansible_network_resources'].pop('system', None)
|
||||
facts = {}
|
||||
if self._subset['fact'].startswith(tuple(SystemArgs.FACT_SYSTEM_SUBSETS)):
|
||||
gather_method = getattr(self, self._subset['fact'].replace('-', '_'), self.system_fact)
|
||||
resp = gather_method()
|
||||
facts.update({self._subset['fact']: resp})
|
||||
|
||||
ansible_facts['ansible_network_resources'].update(facts)
|
||||
return ansible_facts
|
||||
|
||||
def system_fact(self):
|
||||
fos = self._fos
|
||||
vdom = self._module.params['vdom']
|
||||
return fos.monitor('system', self._subset['fact'][len('system_'):].replace('_', '/'), vdom=vdom)
|
||||
|
||||
def system_interface_select(self):
|
||||
fos = self._fos
|
||||
vdom = self._module.params['vdom']
|
||||
|
||||
query_string = '?vdom=' + vdom
|
||||
system_interface_select_param = self._subset['filters']
|
||||
if system_interface_select_param:
|
||||
for filter in system_interface_select_param:
|
||||
for key, val in filter.items():
|
||||
if val:
|
||||
query_string += '&' + str(key) + '=' + str(val)
|
||||
|
||||
return fos.monitor('system', self._subset['fact'][len('system_'):].replace('_', '/') + query_string, vdom=None)
|
||||
@ -1,338 +0,0 @@
|
||||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
#
|
||||
# Copyright (c), Benjamin Jolivot <bjolivot@gmail.com>, 2014,
|
||||
# Miguel Angel Munoz <magonzalez@fortinet.com>, 2019
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
|
||||
#
|
||||
import os
|
||||
import time
|
||||
import traceback
|
||||
|
||||
from ansible.module_utils._text import to_text
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
|
||||
import json
|
||||
|
||||
# BEGIN DEPRECATED
|
||||
|
||||
# check for pyFG lib
|
||||
try:
|
||||
from pyFG import FortiOS, FortiConfig
|
||||
from pyFG.exceptions import FailedCommit
|
||||
HAS_PYFG = True
|
||||
except ImportError:
|
||||
HAS_PYFG = False
|
||||
|
||||
fortios_argument_spec = dict(
|
||||
file_mode=dict(type='bool', default=False),
|
||||
config_file=dict(type='path'),
|
||||
host=dict(),
|
||||
username=dict(fallback=(env_fallback, ['ANSIBLE_NET_USERNAME'])),
|
||||
password=dict(fallback=(env_fallback, ['ANSIBLE_NET_PASSWORD']), no_log=True),
|
||||
timeout=dict(type='int', default=60),
|
||||
vdom=dict(type='str'),
|
||||
backup=dict(type='bool', default=False),
|
||||
backup_path=dict(type='path'),
|
||||
backup_filename=dict(type='str'),
|
||||
)
|
||||
|
||||
fortios_required_if = [
|
||||
['file_mode', False, ['host', 'username', 'password']],
|
||||
['file_mode', True, ['config_file']],
|
||||
['backup', True, ['backup_path']],
|
||||
]
|
||||
|
||||
fortios_mutually_exclusive = [
|
||||
['config_file', 'host'],
|
||||
['config_file', 'username'],
|
||||
['config_file', 'password']
|
||||
]
|
||||
|
||||
fortios_error_codes = {
|
||||
'-3': "Object not found",
|
||||
'-61': "Command error"
|
||||
}
|
||||
|
||||
# END DEPRECATED
|
||||
|
||||
|
||||
class FortiOSHandler(object):
|
||||
|
||||
def __init__(self, conn):
|
||||
self._conn = conn
|
||||
|
||||
def cmdb_url(self, path, name, vdom=None, mkey=None):
|
||||
|
||||
url = '/api/v2/cmdb/' + path + '/' + name
|
||||
if mkey:
|
||||
url = url + '/' + str(mkey)
|
||||
if vdom:
|
||||
if vdom == "global":
|
||||
url += '?global=1'
|
||||
else:
|
||||
url += '?vdom=' + vdom
|
||||
return url
|
||||
|
||||
def mon_url(self, path, name, vdom=None, mkey=None):
|
||||
url = '/api/v2/monitor/' + path + '/' + name
|
||||
if mkey:
|
||||
url = url + '/' + str(mkey)
|
||||
if vdom:
|
||||
if vdom == "global":
|
||||
url += '?global=1'
|
||||
else:
|
||||
url += '?vdom=' + vdom
|
||||
return url
|
||||
|
||||
def schema(self, path, name, vdom=None):
|
||||
if vdom is None:
|
||||
url = self.cmdb_url(path, name) + "?action=schema"
|
||||
else:
|
||||
url = self.cmdb_url(path, name, vdom=vdom) + "&action=schema"
|
||||
|
||||
status, result_data = self._conn.send_request(url=url)
|
||||
|
||||
if status == 200:
|
||||
if vdom == "global":
|
||||
return json.loads(to_text(result_data))[0]['results']
|
||||
else:
|
||||
return json.loads(to_text(result_data))['results']
|
||||
else:
|
||||
return json.loads(to_text(result_data))
|
||||
|
||||
def get_mkeyname(self, path, name, vdom=None):
|
||||
schema = self.schema(path, name, vdom=vdom)
|
||||
try:
|
||||
keyname = schema['mkey']
|
||||
except KeyError:
|
||||
return False
|
||||
return keyname
|
||||
|
||||
def get_mkey(self, path, name, data, vdom=None):
|
||||
|
||||
keyname = self.get_mkeyname(path, name, vdom)
|
||||
if not keyname:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
mkey = data[keyname]
|
||||
except KeyError:
|
||||
return None
|
||||
return mkey
|
||||
|
||||
def get(self, path, name, vdom=None, mkey=None, parameters=None):
|
||||
url = self.cmdb_url(path, name, vdom, mkey=mkey)
|
||||
|
||||
status, result_data = self._conn.send_request(url=url, params=parameters, method='GET')
|
||||
|
||||
return self.formatresponse(result_data, vdom=vdom)
|
||||
|
||||
def monitor(self, path, name, vdom=None, mkey=None, parameters=None):
|
||||
url = self.mon_url(path, name, vdom, mkey)
|
||||
|
||||
status, result_data = self._conn.send_request(url=url, params=parameters, method='GET')
|
||||
|
||||
return self.formatresponse(result_data, vdom=vdom)
|
||||
|
||||
def set(self, path, name, data, mkey=None, vdom=None, parameters=None):
|
||||
|
||||
if not mkey:
|
||||
mkey = self.get_mkey(path, name, data, vdom=vdom)
|
||||
url = self.cmdb_url(path, name, vdom, mkey)
|
||||
|
||||
status, result_data = self._conn.send_request(url=url, params=parameters, data=json.dumps(data), method='PUT')
|
||||
|
||||
if status == 404 or status == 405 or status == 500:
|
||||
return self.post(path, name, data, vdom, mkey)
|
||||
else:
|
||||
return self.formatresponse(result_data, vdom=vdom)
|
||||
|
||||
def post(self, path, name, data, vdom=None,
|
||||
mkey=None, parameters=None):
|
||||
|
||||
if mkey:
|
||||
mkeyname = self.get_mkeyname(path, name, vdom)
|
||||
data[mkeyname] = mkey
|
||||
|
||||
url = self.cmdb_url(path, name, vdom, mkey=None)
|
||||
|
||||
status, result_data = self._conn.send_request(url=url, params=parameters, data=json.dumps(data), method='POST')
|
||||
|
||||
return self.formatresponse(result_data, vdom=vdom)
|
||||
|
||||
def execute(self, path, name, data, vdom=None,
|
||||
mkey=None, parameters=None, timeout=300):
|
||||
url = self.mon_url(path, name, vdom, mkey=mkey)
|
||||
|
||||
status, result_data = self._conn.send_request(url=url, params=parameters, data=json.dumps(data), method='POST', timeout=timeout)
|
||||
|
||||
return self.formatresponse(result_data, vdom=vdom)
|
||||
|
||||
def delete(self, path, name, vdom=None, mkey=None, parameters=None, data=None):
|
||||
if not mkey:
|
||||
mkey = self.get_mkey(path, name, data, vdom=vdom)
|
||||
url = self.cmdb_url(path, name, vdom, mkey)
|
||||
status, result_data = self._conn.send_request(url=url, params=parameters, data=json.dumps(data), method='DELETE')
|
||||
return self.formatresponse(result_data, vdom=vdom)
|
||||
|
||||
def formatresponse(self, res, vdom=None):
|
||||
if vdom == "global":
|
||||
resp = json.loads(to_text(res))[0]
|
||||
resp['vdom'] = "global"
|
||||
else:
|
||||
resp = json.loads(to_text(res))
|
||||
return resp
|
||||
|
||||
# BEGIN DEPRECATED
|
||||
|
||||
|
||||
def backup(module, running_config):
|
||||
backup_path = module.params['backup_path']
|
||||
backup_filename = module.params['backup_filename']
|
||||
if not os.path.exists(backup_path):
|
||||
try:
|
||||
os.mkdir(backup_path)
|
||||
except Exception:
|
||||
module.fail_json(msg="Can't create directory {0} Permission denied ?".format(backup_path))
|
||||
tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
|
||||
if 0 < len(backup_filename):
|
||||
filename = '%s/%s' % (backup_path, backup_filename)
|
||||
else:
|
||||
filename = '%s/%s_config.%s' % (backup_path, module.params['host'], tstamp)
|
||||
try:
|
||||
open(filename, 'w').write(running_config)
|
||||
except Exception:
|
||||
module.fail_json(msg="Can't create backup file {0} Permission denied ?".format(filename))
|
||||
|
||||
|
||||
class AnsibleFortios(object):
|
||||
def __init__(self, module):
|
||||
if not HAS_PYFG:
|
||||
module.fail_json(msg='Could not import the python library pyFG required by this module')
|
||||
|
||||
self.result = {
|
||||
'changed': False,
|
||||
}
|
||||
self.module = module
|
||||
|
||||
def _connect(self):
|
||||
if self.module.params['file_mode']:
|
||||
self.forti_device = FortiOS('')
|
||||
else:
|
||||
host = self.module.params['host']
|
||||
username = self.module.params['username']
|
||||
password = self.module.params['password']
|
||||
timeout = self.module.params['timeout']
|
||||
vdom = self.module.params['vdom']
|
||||
|
||||
self.forti_device = FortiOS(host, username=username, password=password, timeout=timeout, vdom=vdom)
|
||||
|
||||
try:
|
||||
self.forti_device.open()
|
||||
except Exception as e:
|
||||
self.module.fail_json(msg='Error connecting device. %s' % to_text(e),
|
||||
exception=traceback.format_exc())
|
||||
|
||||
def load_config(self, path):
|
||||
self.path = path
|
||||
self._connect()
|
||||
# load in file_mode
|
||||
if self.module.params['file_mode']:
|
||||
try:
|
||||
f = open(self.module.params['config_file'], 'r')
|
||||
running = f.read()
|
||||
f.close()
|
||||
except IOError as e:
|
||||
self.module.fail_json(msg='Error reading configuration file. %s' % to_text(e),
|
||||
exception=traceback.format_exc())
|
||||
self.forti_device.load_config(config_text=running, path=path)
|
||||
|
||||
else:
|
||||
# get config
|
||||
try:
|
||||
self.forti_device.load_config(path=path)
|
||||
except Exception as e:
|
||||
self.forti_device.close()
|
||||
self.module.fail_json(msg='Error reading running config. %s' % to_text(e),
|
||||
exception=traceback.format_exc())
|
||||
|
||||
# set configs in object
|
||||
self.result['running_config'] = self.forti_device.running_config.to_text()
|
||||
self.candidate_config = self.forti_device.candidate_config
|
||||
|
||||
# backup if needed
|
||||
if self.module.params['backup']:
|
||||
backup(self.module, self.forti_device.running_config.to_text())
|
||||
|
||||
def apply_changes(self):
|
||||
change_string = self.forti_device.compare_config()
|
||||
if change_string:
|
||||
self.result['change_string'] = change_string
|
||||
self.result['changed'] = True
|
||||
|
||||
# Commit if not check mode
|
||||
if change_string and not self.module.check_mode:
|
||||
if self.module.params['file_mode']:
|
||||
try:
|
||||
f = open(self.module.params['config_file'], 'w')
|
||||
f.write(self.candidate_config.to_text())
|
||||
f.close()
|
||||
except IOError as e:
|
||||
self.module.fail_json(msg='Error writing configuration file. %s' %
|
||||
to_text(e), exception=traceback.format_exc())
|
||||
else:
|
||||
try:
|
||||
self.forti_device.commit()
|
||||
except FailedCommit as e:
|
||||
# Something's wrong (rollback is automatic)
|
||||
self.forti_device.close()
|
||||
error_list = self.get_error_infos(e)
|
||||
self.module.fail_json(msg_error_list=error_list, msg="Unable to commit change, check your args, the error was %s" % e.message)
|
||||
|
||||
self.forti_device.close()
|
||||
self.module.exit_json(**self.result)
|
||||
|
||||
def del_block(self, block_id):
|
||||
self.forti_device.candidate_config[self.path].del_block(block_id)
|
||||
|
||||
def add_block(self, block_id, block):
|
||||
self.forti_device.candidate_config[self.path][block_id] = block
|
||||
|
||||
def get_error_infos(self, cli_errors):
|
||||
error_list = []
|
||||
for errors in cli_errors.args:
|
||||
for error in errors:
|
||||
error_code = error[0]
|
||||
error_string = error[1]
|
||||
error_type = fortios_error_codes.get(error_code, "unknown")
|
||||
error_list.append(dict(error_code=error_code, error_type=error_type, error_string=error_string))
|
||||
|
||||
return error_list
|
||||
|
||||
def get_empty_configuration_block(self, block_name, block_type):
|
||||
return FortiConfig(block_name, block_type)
|
||||
|
||||
# END DEPRECATED
|
||||
@ -1,291 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Ansible module to manage IP addresses on fortios devices
|
||||
# (c) 2016, Benjamin Jolivot <bjolivot@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: fortios_address
|
||||
version_added: "2.4"
|
||||
author: "Benjamin Jolivot (@bjolivot)"
|
||||
short_description: Manage fortios firewall address objects
|
||||
description:
|
||||
- This module provide management of firewall addresses on FortiOS devices.
|
||||
extends_documentation_fragment: fortios
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Specifies if address need to be added or deleted.
|
||||
required: true
|
||||
choices: ['present', 'absent']
|
||||
name:
|
||||
description:
|
||||
- Name of the address to add or delete.
|
||||
required: true
|
||||
type:
|
||||
description:
|
||||
- Type of the address.
|
||||
choices: ['iprange', 'fqdn', 'ipmask', 'geography']
|
||||
value:
|
||||
description:
|
||||
- Address value, based on type.
|
||||
If type=fqdn, something like www.google.com.
|
||||
If type=ipmask, you can use simple ip (192.168.0.1), ip+mask (192.168.0.1 255.255.255.0) or CIDR (192.168.0.1/32).
|
||||
start_ip:
|
||||
description:
|
||||
- First ip in range (used only with type=iprange).
|
||||
end_ip:
|
||||
description:
|
||||
- Last ip in range (used only with type=iprange).
|
||||
country:
|
||||
description:
|
||||
- 2 letter country code (like FR).
|
||||
interface:
|
||||
description:
|
||||
- interface name the address apply to.
|
||||
default: any
|
||||
comment:
|
||||
description:
|
||||
- free text to describe address.
|
||||
notes:
|
||||
- This module requires netaddr python library.
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Register french addresses
|
||||
fortios_address:
|
||||
host: 192.168.0.254
|
||||
username: admin
|
||||
password: p4ssw0rd
|
||||
state: present
|
||||
name: "fromfrance"
|
||||
type: geography
|
||||
country: FR
|
||||
comment: "French geoip address"
|
||||
|
||||
- name: Register some fqdn
|
||||
fortios_address:
|
||||
host: 192.168.0.254
|
||||
username: admin
|
||||
password: p4ssw0rd
|
||||
state: present
|
||||
name: "Ansible"
|
||||
type: fqdn
|
||||
value: www.ansible.com
|
||||
comment: "Ansible website"
|
||||
|
||||
- name: Register google DNS
|
||||
fortios_address:
|
||||
host: 192.168.0.254
|
||||
username: admin
|
||||
password: p4ssw0rd
|
||||
state: present
|
||||
name: "google_dns"
|
||||
type: ipmask
|
||||
value: 8.8.8.8
|
||||
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
firewall_address_config:
|
||||
description: full firewall addresses config string.
|
||||
returned: always
|
||||
type: str
|
||||
change_string:
|
||||
description: The commands executed by the module.
|
||||
returned: only if config changed
|
||||
type: str
|
||||
"""
|
||||
|
||||
from ansible.module_utils.network.fortios.fortios import fortios_argument_spec, fortios_required_if
|
||||
from ansible.module_utils.network.fortios.fortios import backup, AnsibleFortios
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
# check for netaddr lib
|
||||
try:
|
||||
from netaddr import IPNetwork
|
||||
HAS_NETADDR = True
|
||||
except Exception:
|
||||
HAS_NETADDR = False
|
||||
|
||||
|
||||
# define valid country list for GEOIP address type
|
||||
FG_COUNTRY_LIST = (
|
||||
'ZZ', 'A1', 'A2', 'O1', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AN', 'AO',
|
||||
'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE',
|
||||
'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT',
|
||||
'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL',
|
||||
'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK',
|
||||
'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'EU', 'FI', 'FJ',
|
||||
'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL',
|
||||
'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN',
|
||||
'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT',
|
||||
'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW',
|
||||
'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY',
|
||||
'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP',
|
||||
'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE',
|
||||
'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF',
|
||||
'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE',
|
||||
'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ',
|
||||
'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ', 'TC',
|
||||
'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV',
|
||||
'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI',
|
||||
'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW'
|
||||
)
|
||||
|
||||
|
||||
def get_formated_ipaddr(input_ip):
|
||||
"""
|
||||
Format given ip address string to fortigate format (ip netmask)
|
||||
Args:
|
||||
* **ip_str** (string) : string representing ip address
|
||||
accepted format:
|
||||
- ip netmask (ex: 192.168.0.10 255.255.255.0)
|
||||
- ip (ex: 192.168.0.10)
|
||||
- CIDR (ex: 192.168.0.10/24)
|
||||
|
||||
Returns:
|
||||
formated ip if ip is valid (ex: "192.168.0.10 255.255.255.0")
|
||||
False if ip is not valid
|
||||
"""
|
||||
try:
|
||||
if " " in input_ip:
|
||||
# ip netmask format
|
||||
str_ip, str_netmask = input_ip.split(" ")
|
||||
ip = IPNetwork(str_ip)
|
||||
mask = IPNetwork(str_netmask)
|
||||
return "%s %s" % (str_ip, str_netmask)
|
||||
else:
|
||||
ip = IPNetwork(input_ip)
|
||||
return "%s %s" % (str(ip.ip), str(ip.netmask))
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
state=dict(required=True, choices=['present', 'absent']),
|
||||
name=dict(required=True),
|
||||
type=dict(choices=['iprange', 'fqdn', 'ipmask', 'geography'], default='ipmask'),
|
||||
value=dict(),
|
||||
start_ip=dict(),
|
||||
end_ip=dict(),
|
||||
country=dict(),
|
||||
interface=dict(default='any'),
|
||||
comment=dict(),
|
||||
)
|
||||
|
||||
# merge argument_spec from module_utils/fortios.py
|
||||
argument_spec.update(fortios_argument_spec)
|
||||
|
||||
# Load module
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
required_if=fortios_required_if,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
result = dict(changed=False)
|
||||
|
||||
if not HAS_NETADDR:
|
||||
module.fail_json(msg='Could not import the python library netaddr required by this module')
|
||||
|
||||
# check params
|
||||
if module.params['state'] == 'absent':
|
||||
if module.params['type'] != "ipmask":
|
||||
module.fail_json(msg='Invalid argument type=%s when state=absent' % module.params['type'])
|
||||
if module.params['value'] is not None:
|
||||
module.fail_json(msg='Invalid argument `value` when state=absent')
|
||||
if module.params['start_ip'] is not None:
|
||||
module.fail_json(msg='Invalid argument `start_ip` when state=absent')
|
||||
if module.params['end_ip'] is not None:
|
||||
module.fail_json(msg='Invalid argument `end_ip` when state=absent')
|
||||
if module.params['country'] is not None:
|
||||
module.fail_json(msg='Invalid argument `country` when state=absent')
|
||||
if module.params['interface'] != "any":
|
||||
module.fail_json(msg='Invalid argument `interface` when state=absent')
|
||||
if module.params['comment'] is not None:
|
||||
module.fail_json(msg='Invalid argument `comment` when state=absent')
|
||||
else:
|
||||
# state=present
|
||||
# validate IP
|
||||
if module.params['type'] == "ipmask":
|
||||
formated_ip = get_formated_ipaddr(module.params['value'])
|
||||
if formated_ip is not False:
|
||||
module.params['value'] = get_formated_ipaddr(module.params['value'])
|
||||
else:
|
||||
module.fail_json(msg="Bad ip address format")
|
||||
|
||||
# validate country
|
||||
if module.params['type'] == "geography":
|
||||
if module.params['country'] not in FG_COUNTRY_LIST:
|
||||
module.fail_json(msg="Invalid country argument, need to be in `diagnose firewall ipgeo country-list`")
|
||||
|
||||
# validate iprange
|
||||
if module.params['type'] == "iprange":
|
||||
if module.params['start_ip'] is None:
|
||||
module.fail_json(msg="Missing argument 'start_ip' when type is iprange")
|
||||
if module.params['end_ip'] is None:
|
||||
module.fail_json(msg="Missing argument 'end_ip' when type is iprange")
|
||||
|
||||
# init forti object
|
||||
fortigate = AnsibleFortios(module)
|
||||
|
||||
# Config path
|
||||
config_path = 'firewall address'
|
||||
|
||||
# load config
|
||||
fortigate.load_config(config_path)
|
||||
|
||||
# Absent State
|
||||
if module.params['state'] == 'absent':
|
||||
fortigate.candidate_config[config_path].del_block(module.params['name'])
|
||||
|
||||
# Present state
|
||||
if module.params['state'] == 'present':
|
||||
# define address params
|
||||
new_addr = fortigate.get_empty_configuration_block(module.params['name'], 'edit')
|
||||
|
||||
if module.params['comment'] is not None:
|
||||
new_addr.set_param('comment', '"%s"' % (module.params['comment']))
|
||||
|
||||
if module.params['type'] == 'iprange':
|
||||
new_addr.set_param('type', 'iprange')
|
||||
new_addr.set_param('start-ip', module.params['start_ip'])
|
||||
new_addr.set_param('end-ip', module.params['end_ip'])
|
||||
|
||||
if module.params['type'] == 'geography':
|
||||
new_addr.set_param('type', 'geography')
|
||||
new_addr.set_param('country', '"%s"' % (module.params['country']))
|
||||
|
||||
if module.params['interface'] != 'any':
|
||||
new_addr.set_param('associated-interface', '"%s"' % (module.params['interface']))
|
||||
|
||||
if module.params['value'] is not None:
|
||||
if module.params['type'] == 'fqdn':
|
||||
new_addr.set_param('type', 'fqdn')
|
||||
new_addr.set_param('fqdn', '"%s"' % (module.params['value']))
|
||||
if module.params['type'] == 'ipmask':
|
||||
new_addr.set_param('subnet', module.params['value'])
|
||||
|
||||
# add the new address object to the device
|
||||
fortigate.add_block(module.params['name'], new_addr)
|
||||
|
||||
# Apply changes (check mode is managed directly by the fortigate object)
|
||||
fortigate.apply_changes()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,602 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_alertemail_setting
|
||||
short_description: Configure alert email settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify alertemail feature and setting category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.9"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
alertemail_setting:
|
||||
description:
|
||||
- Configure alert email settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
admin_login_logs:
|
||||
description:
|
||||
- Enable/disable administrator login/logout logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
alert_interval:
|
||||
description:
|
||||
- Alert alert interval in minutes.
|
||||
type: int
|
||||
amc_interface_bypass_mode:
|
||||
description:
|
||||
- Enable/disable Fortinet Advanced Mezzanine Card (AMC) interface bypass mode logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
antivirus_logs:
|
||||
description:
|
||||
- Enable/disable antivirus logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
configuration_changes_logs:
|
||||
description:
|
||||
- Enable/disable configuration change logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
critical_interval:
|
||||
description:
|
||||
- Critical alert interval in minutes.
|
||||
type: int
|
||||
debug_interval:
|
||||
description:
|
||||
- Debug alert interval in minutes.
|
||||
type: int
|
||||
email_interval:
|
||||
description:
|
||||
- Interval between sending alert emails (1 - 99999 min).
|
||||
type: int
|
||||
emergency_interval:
|
||||
description:
|
||||
- Emergency alert interval in minutes.
|
||||
type: int
|
||||
error_interval:
|
||||
description:
|
||||
- Error alert interval in minutes.
|
||||
type: int
|
||||
FDS_license_expiring_days:
|
||||
description:
|
||||
- Number of days to send alert email prior to FortiGuard license expiration (1 - 100 days).
|
||||
type: int
|
||||
FDS_license_expiring_warning:
|
||||
description:
|
||||
- Enable/disable FortiGuard license expiration warnings in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
FDS_update_logs:
|
||||
description:
|
||||
- Enable/disable FortiGuard update logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
filter_mode:
|
||||
description:
|
||||
- How to filter log messages that are sent to alert emails.
|
||||
type: str
|
||||
choices:
|
||||
- category
|
||||
- threshold
|
||||
FIPS_CC_errors:
|
||||
description:
|
||||
- Enable/disable FIPS and Common Criteria error logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
firewall_authentication_failure_logs:
|
||||
description:
|
||||
- Enable/disable firewall authentication failure logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
fortiguard_log_quota_warning:
|
||||
description:
|
||||
- Enable/disable FortiCloud log quota warnings in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
FSSO_disconnect_logs:
|
||||
description:
|
||||
- Enable/disable logging of FSSO collector agent disconnect.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
HA_logs:
|
||||
description:
|
||||
- Enable/disable HA logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
information_interval:
|
||||
description:
|
||||
- Information alert interval in minutes.
|
||||
type: int
|
||||
IPS_logs:
|
||||
description:
|
||||
- Enable/disable IPS logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
IPsec_errors_logs:
|
||||
description:
|
||||
- Enable/disable IPsec error logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
local_disk_usage:
|
||||
description:
|
||||
- Disk usage percentage at which to send alert email (1 - 99 percent).
|
||||
type: int
|
||||
log_disk_usage_warning:
|
||||
description:
|
||||
- Enable/disable disk usage warnings in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
mailto1:
|
||||
description:
|
||||
- Email address to send alert email to (usually a system administrator) (max. 64 characters).
|
||||
type: str
|
||||
mailto2:
|
||||
description:
|
||||
- Optional second email address to send alert email to (max. 64 characters).
|
||||
type: str
|
||||
mailto3:
|
||||
description:
|
||||
- Optional third email address to send alert email to (max. 64 characters).
|
||||
type: str
|
||||
notification_interval:
|
||||
description:
|
||||
- Notification alert interval in minutes.
|
||||
type: int
|
||||
PPP_errors_logs:
|
||||
description:
|
||||
- Enable/disable PPP error logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
severity:
|
||||
description:
|
||||
- Lowest severity level to log.
|
||||
type: str
|
||||
choices:
|
||||
- emergency
|
||||
- alert
|
||||
- critical
|
||||
- error
|
||||
- warning
|
||||
- notification
|
||||
- information
|
||||
- debug
|
||||
ssh_logs:
|
||||
description:
|
||||
- Enable/disable SSH logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
sslvpn_authentication_errors_logs:
|
||||
description:
|
||||
- Enable/disable SSL-VPN authentication error logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
username:
|
||||
description:
|
||||
- "Name that appears in the From: field of alert emails (max. 36 characters)."
|
||||
type: str
|
||||
violation_traffic_logs:
|
||||
description:
|
||||
- Enable/disable violation traffic logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
warning_interval:
|
||||
description:
|
||||
- Warning alert interval in minutes.
|
||||
type: int
|
||||
webfilter_logs:
|
||||
description:
|
||||
- Enable/disable web filter logs in alert email.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure alert email settings.
|
||||
fortios_alertemail_setting:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
alertemail_setting:
|
||||
admin_login_logs: "enable"
|
||||
alert_interval: "4"
|
||||
amc_interface_bypass_mode: "enable"
|
||||
antivirus_logs: "enable"
|
||||
configuration_changes_logs: "enable"
|
||||
critical_interval: "8"
|
||||
debug_interval: "9"
|
||||
email_interval: "10"
|
||||
emergency_interval: "11"
|
||||
error_interval: "12"
|
||||
FDS_license_expiring_days: "13"
|
||||
FDS_license_expiring_warning: "enable"
|
||||
FDS_update_logs: "enable"
|
||||
filter_mode: "category"
|
||||
FIPS_CC_errors: "enable"
|
||||
firewall_authentication_failure_logs: "enable"
|
||||
fortiguard_log_quota_warning: "enable"
|
||||
FSSO_disconnect_logs: "enable"
|
||||
HA_logs: "enable"
|
||||
information_interval: "22"
|
||||
IPS_logs: "enable"
|
||||
IPsec_errors_logs: "enable"
|
||||
local_disk_usage: "25"
|
||||
log_disk_usage_warning: "enable"
|
||||
mailto1: "<your_own_value>"
|
||||
mailto2: "<your_own_value>"
|
||||
mailto3: "<your_own_value>"
|
||||
notification_interval: "30"
|
||||
PPP_errors_logs: "enable"
|
||||
severity: "emergency"
|
||||
ssh_logs: "enable"
|
||||
sslvpn_authentication_errors_logs: "enable"
|
||||
username: "<your_own_value>"
|
||||
violation_traffic_logs: "enable"
|
||||
warning_interval: "37"
|
||||
webfilter_logs: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_alertemail_setting_data(json):
|
||||
option_list = ['admin_login_logs', 'alert_interval', 'amc_interface_bypass_mode',
|
||||
'antivirus_logs', 'configuration_changes_logs', 'critical_interval',
|
||||
'debug_interval', 'email_interval', 'emergency_interval',
|
||||
'error_interval', 'FDS_license_expiring_days', 'FDS_license_expiring_warning',
|
||||
'FDS_update_logs', 'filter_mode', 'FIPS_CC_errors',
|
||||
'firewall_authentication_failure_logs', 'fortiguard_log_quota_warning', 'FSSO_disconnect_logs',
|
||||
'HA_logs', 'information_interval', 'IPS_logs',
|
||||
'IPsec_errors_logs', 'local_disk_usage', 'log_disk_usage_warning',
|
||||
'mailto1', 'mailto2', 'mailto3',
|
||||
'notification_interval', 'PPP_errors_logs', 'severity',
|
||||
'ssh_logs', 'sslvpn_authentication_errors_logs', 'username',
|
||||
'violation_traffic_logs', 'warning_interval', 'webfilter_logs']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def alertemail_setting(data, fos):
|
||||
vdom = data['vdom']
|
||||
alertemail_setting_data = data['alertemail_setting']
|
||||
filtered_data = underscore_to_hyphen(filter_alertemail_setting_data(alertemail_setting_data))
|
||||
|
||||
return fos.set('alertemail',
|
||||
'setting',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_alertemail(data, fos):
|
||||
|
||||
if data['alertemail_setting']:
|
||||
resp = alertemail_setting(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"alertemail_setting": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"admin_login_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"alert_interval": {"required": False, "type": "int"},
|
||||
"amc_interface_bypass_mode": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"antivirus_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"configuration_changes_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"critical_interval": {"required": False, "type": "int"},
|
||||
"debug_interval": {"required": False, "type": "int"},
|
||||
"email_interval": {"required": False, "type": "int"},
|
||||
"emergency_interval": {"required": False, "type": "int"},
|
||||
"error_interval": {"required": False, "type": "int"},
|
||||
"FDS_license_expiring_days": {"required": False, "type": "int"},
|
||||
"FDS_license_expiring_warning": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"FDS_update_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"filter_mode": {"required": False, "type": "str",
|
||||
"choices": ["category", "threshold"]},
|
||||
"FIPS_CC_errors": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"firewall_authentication_failure_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"fortiguard_log_quota_warning": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"FSSO_disconnect_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"HA_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"information_interval": {"required": False, "type": "int"},
|
||||
"IPS_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"IPsec_errors_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"local_disk_usage": {"required": False, "type": "int"},
|
||||
"log_disk_usage_warning": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"mailto1": {"required": False, "type": "str"},
|
||||
"mailto2": {"required": False, "type": "str"},
|
||||
"mailto3": {"required": False, "type": "str"},
|
||||
"notification_interval": {"required": False, "type": "int"},
|
||||
"PPP_errors_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"severity": {"required": False, "type": "str",
|
||||
"choices": ["emergency", "alert", "critical",
|
||||
"error", "warning", "notification",
|
||||
"information", "debug"]},
|
||||
"ssh_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"sslvpn_authentication_errors_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"violation_traffic_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"warning_interval": {"required": False, "type": "int"},
|
||||
"webfilter_logs": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_alertemail(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_alertemail(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,295 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_antivirus_heuristic
|
||||
short_description: Configure global heuristic options in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify antivirus feature and heuristic category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
antivirus_heuristic:
|
||||
description:
|
||||
- Configure global heuristic options.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
mode:
|
||||
description:
|
||||
- Enable/disable heuristics and determine how the system behaves if heuristics detects a problem.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure global heuristic options.
|
||||
fortios_antivirus_heuristic:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
antivirus_heuristic:
|
||||
mode: "pass"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_antivirus_heuristic_data(json):
|
||||
option_list = ['mode']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def antivirus_heuristic(data, fos):
|
||||
vdom = data['vdom']
|
||||
antivirus_heuristic_data = data['antivirus_heuristic']
|
||||
filtered_data = underscore_to_hyphen(filter_antivirus_heuristic_data(antivirus_heuristic_data))
|
||||
|
||||
return fos.set('antivirus',
|
||||
'heuristic',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_antivirus(data, fos):
|
||||
|
||||
if data['antivirus_heuristic']:
|
||||
resp = antivirus_heuristic(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"antivirus_heuristic": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"mode": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_antivirus(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_antivirus(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,505 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_antivirus_quarantine
|
||||
short_description: Configure quarantine options in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify antivirus feature and quarantine category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
antivirus_quarantine:
|
||||
description:
|
||||
- Configure quarantine options.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
agelimit:
|
||||
description:
|
||||
- Age limit for quarantined files (0 - 479 hours, 0 means forever).
|
||||
type: int
|
||||
destination:
|
||||
description:
|
||||
- Choose whether to quarantine files to the FortiGate disk or to FortiAnalyzer or to delete them instead of quarantining them.
|
||||
type: str
|
||||
choices:
|
||||
- NULL
|
||||
- disk
|
||||
- FortiAnalyzer
|
||||
drop_blocked:
|
||||
description:
|
||||
- Do not quarantine dropped files found in sessions using the selected protocols. Dropped files are deleted instead of being quarantined.
|
||||
type: str
|
||||
choices:
|
||||
- imap
|
||||
- smtp
|
||||
- pop3
|
||||
- http
|
||||
- ftp
|
||||
- nntp
|
||||
- imaps
|
||||
- smtps
|
||||
- pop3s
|
||||
- ftps
|
||||
- mapi
|
||||
- cifs
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
drop_heuristic:
|
||||
description:
|
||||
- Do not quarantine files detected by heuristics found in sessions using the selected protocols. Dropped files are deleted instead of
|
||||
being quarantined.
|
||||
type: str
|
||||
choices:
|
||||
- imap
|
||||
- smtp
|
||||
- pop3
|
||||
- http
|
||||
- ftp
|
||||
- nntp
|
||||
- imaps
|
||||
- smtps
|
||||
- pop3s
|
||||
- https
|
||||
- ftps
|
||||
- mapi
|
||||
- cifs
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
drop_infected:
|
||||
description:
|
||||
- Do not quarantine infected files found in sessions using the selected protocols. Dropped files are deleted instead of being quarantined.
|
||||
type: str
|
||||
choices:
|
||||
- imap
|
||||
- smtp
|
||||
- pop3
|
||||
- http
|
||||
- ftp
|
||||
- nntp
|
||||
- imaps
|
||||
- smtps
|
||||
- pop3s
|
||||
- https
|
||||
- ftps
|
||||
- mapi
|
||||
- cifs
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
lowspace:
|
||||
description:
|
||||
- Select the method for handling additional files when running low on disk space.
|
||||
type: str
|
||||
choices:
|
||||
- drop-new
|
||||
- ovrw-old
|
||||
maxfilesize:
|
||||
description:
|
||||
- Maximum file size to quarantine (0 - 500 Mbytes, 0 means unlimited).
|
||||
type: int
|
||||
quarantine_quota:
|
||||
description:
|
||||
- The amount of disk space to reserve for quarantining files (0 - 4294967295 Mbytes, depends on disk space).
|
||||
type: int
|
||||
store_blocked:
|
||||
description:
|
||||
- Quarantine blocked files found in sessions using the selected protocols.
|
||||
type: str
|
||||
choices:
|
||||
- imap
|
||||
- smtp
|
||||
- pop3
|
||||
- http
|
||||
- ftp
|
||||
- nntp
|
||||
- imaps
|
||||
- smtps
|
||||
- pop3s
|
||||
- ftps
|
||||
- mapi
|
||||
- cifs
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
store_heuristic:
|
||||
description:
|
||||
- Quarantine files detected by heuristics found in sessions using the selected protocols.
|
||||
type: str
|
||||
choices:
|
||||
- imap
|
||||
- smtp
|
||||
- pop3
|
||||
- http
|
||||
- ftp
|
||||
- nntp
|
||||
- imaps
|
||||
- smtps
|
||||
- pop3s
|
||||
- https
|
||||
- ftps
|
||||
- mapi
|
||||
- cifs
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
store_infected:
|
||||
description:
|
||||
- Quarantine infected files found in sessions using the selected protocols.
|
||||
type: str
|
||||
choices:
|
||||
- imap
|
||||
- smtp
|
||||
- pop3
|
||||
- http
|
||||
- ftp
|
||||
- nntp
|
||||
- imaps
|
||||
- smtps
|
||||
- pop3s
|
||||
- https
|
||||
- ftps
|
||||
- mapi
|
||||
- cifs
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure quarantine options.
|
||||
fortios_antivirus_quarantine:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
antivirus_quarantine:
|
||||
agelimit: "3"
|
||||
destination: "NULL"
|
||||
drop_blocked: "imap"
|
||||
drop_heuristic: "imap"
|
||||
drop_infected: "imap"
|
||||
lowspace: "drop-new"
|
||||
maxfilesize: "9"
|
||||
quarantine_quota: "10"
|
||||
store_blocked: "imap"
|
||||
store_heuristic: "imap"
|
||||
store_infected: "imap"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_antivirus_quarantine_data(json):
|
||||
option_list = ['agelimit', 'destination', 'drop_blocked',
|
||||
'drop_heuristic', 'drop_infected', 'lowspace',
|
||||
'maxfilesize', 'quarantine_quota', 'store_blocked',
|
||||
'store_heuristic', 'store_infected']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def antivirus_quarantine(data, fos):
|
||||
vdom = data['vdom']
|
||||
antivirus_quarantine_data = data['antivirus_quarantine']
|
||||
filtered_data = underscore_to_hyphen(filter_antivirus_quarantine_data(antivirus_quarantine_data))
|
||||
|
||||
return fos.set('antivirus',
|
||||
'quarantine',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_antivirus(data, fos):
|
||||
|
||||
if data['antivirus_quarantine']:
|
||||
resp = antivirus_quarantine(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"antivirus_quarantine": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"agelimit": {"required": False, "type": "int"},
|
||||
"destination": {"required": False, "type": "str",
|
||||
"choices": ["NULL", "disk", "FortiAnalyzer"]},
|
||||
"drop_blocked": {"required": False, "type": "str",
|
||||
"choices": ["imap", "smtp", "pop3",
|
||||
"http", "ftp", "nntp",
|
||||
"imaps", "smtps", "pop3s",
|
||||
"ftps", "mapi", "cifs",
|
||||
"mm1", "mm3", "mm4",
|
||||
"mm7"]},
|
||||
"drop_heuristic": {"required": False, "type": "str",
|
||||
"choices": ["imap", "smtp", "pop3",
|
||||
"http", "ftp", "nntp",
|
||||
"imaps", "smtps", "pop3s",
|
||||
"https", "ftps", "mapi",
|
||||
"cifs", "mm1", "mm3",
|
||||
"mm4", "mm7"]},
|
||||
"drop_infected": {"required": False, "type": "str",
|
||||
"choices": ["imap", "smtp", "pop3",
|
||||
"http", "ftp", "nntp",
|
||||
"imaps", "smtps", "pop3s",
|
||||
"https", "ftps", "mapi",
|
||||
"cifs", "mm1", "mm3",
|
||||
"mm4", "mm7"]},
|
||||
"lowspace": {"required": False, "type": "str",
|
||||
"choices": ["drop-new", "ovrw-old"]},
|
||||
"maxfilesize": {"required": False, "type": "int"},
|
||||
"quarantine_quota": {"required": False, "type": "int"},
|
||||
"store_blocked": {"required": False, "type": "str",
|
||||
"choices": ["imap", "smtp", "pop3",
|
||||
"http", "ftp", "nntp",
|
||||
"imaps", "smtps", "pop3s",
|
||||
"ftps", "mapi", "cifs",
|
||||
"mm1", "mm3", "mm4",
|
||||
"mm7"]},
|
||||
"store_heuristic": {"required": False, "type": "str",
|
||||
"choices": ["imap", "smtp", "pop3",
|
||||
"http", "ftp", "nntp",
|
||||
"imaps", "smtps", "pop3s",
|
||||
"https", "ftps", "mapi",
|
||||
"cifs", "mm1", "mm3",
|
||||
"mm4", "mm7"]},
|
||||
"store_infected": {"required": False, "type": "str",
|
||||
"choices": ["imap", "smtp", "pop3",
|
||||
"http", "ftp", "nntp",
|
||||
"imaps", "smtps", "pop3s",
|
||||
"https", "ftps", "mapi",
|
||||
"cifs", "mm1", "mm3",
|
||||
"mm4", "mm7"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_antivirus(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_antivirus(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,312 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_antivirus_settings
|
||||
short_description: Configure AntiVirus settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify antivirus feature and settings category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
antivirus_settings:
|
||||
description:
|
||||
- Configure AntiVirus settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
default_db:
|
||||
description:
|
||||
- Select the AV database to be used for AV scanning.
|
||||
type: str
|
||||
choices:
|
||||
- normal
|
||||
- extended
|
||||
- extreme
|
||||
grayware:
|
||||
description:
|
||||
- Enable/disable grayware detection when an AntiVirus profile is applied to traffic.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
override_timeout:
|
||||
description:
|
||||
- Override the large file scan timeout value in seconds (30 - 3600). Zero is the default value and is used to disable this command. When
|
||||
disabled, the daemon adjusts the large file scan timeout based on the file size.
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure AntiVirus settings.
|
||||
fortios_antivirus_settings:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
antivirus_settings:
|
||||
default_db: "normal"
|
||||
grayware: "enable"
|
||||
override_timeout: "5"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_antivirus_settings_data(json):
|
||||
option_list = ['default_db', 'grayware', 'override_timeout']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def antivirus_settings(data, fos):
|
||||
vdom = data['vdom']
|
||||
antivirus_settings_data = data['antivirus_settings']
|
||||
filtered_data = underscore_to_hyphen(filter_antivirus_settings_data(antivirus_settings_data))
|
||||
|
||||
return fos.set('antivirus',
|
||||
'settings',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_antivirus(data, fos):
|
||||
|
||||
if data['antivirus_settings']:
|
||||
resp = antivirus_settings(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"antivirus_settings": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"default_db": {"required": False, "type": "str",
|
||||
"choices": ["normal", "extended", "extreme"]},
|
||||
"grayware": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"override_timeout": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_antivirus(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_antivirus(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,388 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_application_custom
|
||||
short_description: Configure custom application signatures in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify application feature and custom category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
application_custom:
|
||||
description:
|
||||
- Configure custom application signatures.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
behavior:
|
||||
description:
|
||||
- Custom application signature behavior.
|
||||
type: str
|
||||
category:
|
||||
description:
|
||||
- Custom application category ID (use ? to view available options).
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Custom application category ID (use ? to view available options).
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Name of this custom application signature.
|
||||
type: str
|
||||
protocol:
|
||||
description:
|
||||
- Custom application signature protocol.
|
||||
type: str
|
||||
signature:
|
||||
description:
|
||||
- The text that makes up the actual custom application signature.
|
||||
type: str
|
||||
tag:
|
||||
description:
|
||||
- Signature tag.
|
||||
required: true
|
||||
type: str
|
||||
technology:
|
||||
description:
|
||||
- Custom application signature technology.
|
||||
type: str
|
||||
vendor:
|
||||
description:
|
||||
- Custom application signature vendor.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure custom application signatures.
|
||||
fortios_application_custom:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
application_custom:
|
||||
behavior: "<your_own_value>"
|
||||
category: "4"
|
||||
comment: "Comment."
|
||||
id: "6"
|
||||
name: "default_name_7"
|
||||
protocol: "<your_own_value>"
|
||||
signature: "<your_own_value>"
|
||||
tag: "<your_own_value>"
|
||||
technology: "<your_own_value>"
|
||||
vendor: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_application_custom_data(json):
|
||||
option_list = ['behavior', 'category', 'comment',
|
||||
'id', 'name', 'protocol',
|
||||
'signature', 'tag', 'technology',
|
||||
'vendor']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def application_custom(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['application_custom'] and data['application_custom']:
|
||||
state = data['application_custom']['state']
|
||||
else:
|
||||
state = True
|
||||
application_custom_data = data['application_custom']
|
||||
filtered_data = underscore_to_hyphen(filter_application_custom_data(application_custom_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('application',
|
||||
'custom',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('application',
|
||||
'custom',
|
||||
mkey=filtered_data['tag'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_application(data, fos):
|
||||
|
||||
if data['application_custom']:
|
||||
resp = application_custom(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application_custom": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"behavior": {"required": False, "type": "str"},
|
||||
"category": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"id": {"required": False, "type": "int"},
|
||||
"name": {"required": False, "type": "str"},
|
||||
"protocol": {"required": False, "type": "str"},
|
||||
"signature": {"required": False, "type": "str"},
|
||||
"tag": {"required": True, "type": "str"},
|
||||
"technology": {"required": False, "type": "str"},
|
||||
"vendor": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,382 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_application_group
|
||||
short_description: Configure firewall application groups in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify application feature and group category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
application_group:
|
||||
description:
|
||||
- Configure firewall application groups.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
application:
|
||||
description:
|
||||
- Application ID list.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application IDs.
|
||||
required: true
|
||||
type: int
|
||||
category:
|
||||
description:
|
||||
- Application category ID list.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Category IDs.
|
||||
required: true
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Application group name.
|
||||
required: true
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Application group type.
|
||||
type: str
|
||||
choices:
|
||||
- application
|
||||
- category
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure firewall application groups.
|
||||
fortios_application_group:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
application_group:
|
||||
application:
|
||||
-
|
||||
id: "4"
|
||||
category:
|
||||
-
|
||||
id: "6"
|
||||
comment: "Comment"
|
||||
name: "default_name_8"
|
||||
type: "application"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_application_group_data(json):
|
||||
option_list = ['application', 'category', 'comment',
|
||||
'name', 'type']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def application_group(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['application_group'] and data['application_group']:
|
||||
state = data['application_group']['state']
|
||||
else:
|
||||
state = True
|
||||
application_group_data = data['application_group']
|
||||
filtered_data = underscore_to_hyphen(filter_application_group_data(application_group_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('application',
|
||||
'group',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('application',
|
||||
'group',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_application(data, fos):
|
||||
|
||||
if data['application_group']:
|
||||
resp = application_group(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application_group": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["application", "category"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,705 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_application_list
|
||||
short_description: Configure application control lists in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify application feature and list category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
application_list:
|
||||
description:
|
||||
- Configure application control lists.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
app_replacemsg:
|
||||
description:
|
||||
- Enable/disable replacement messages for blocked applications.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
comment:
|
||||
description:
|
||||
- comments
|
||||
type: str
|
||||
deep_app_inspection:
|
||||
description:
|
||||
- Enable/disable deep application inspection.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
entries:
|
||||
description:
|
||||
- Application list entries.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Pass or block traffic, or reset connection for traffic from this application.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
- reset
|
||||
application:
|
||||
description:
|
||||
- ID of allowed applications.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application IDs.
|
||||
required: true
|
||||
type: int
|
||||
behavior:
|
||||
description:
|
||||
- Application behavior filter.
|
||||
type: str
|
||||
category:
|
||||
description:
|
||||
- Category ID list.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application category ID.
|
||||
required: true
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- Entry ID.
|
||||
required: true
|
||||
type: int
|
||||
log:
|
||||
description:
|
||||
- Enable/disable logging for this application list.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
log_packet:
|
||||
description:
|
||||
- Enable/disable packet logging.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
parameters:
|
||||
description:
|
||||
- Application parameters.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Parameter ID.
|
||||
required: true
|
||||
type: int
|
||||
value:
|
||||
description:
|
||||
- Parameter value.
|
||||
type: str
|
||||
per_ip_shaper:
|
||||
description:
|
||||
- Per-IP traffic shaper. Source firewall.shaper.per-ip-shaper.name.
|
||||
type: str
|
||||
popularity:
|
||||
description:
|
||||
- Application popularity filter (1 - 5, from least to most popular).
|
||||
type: str
|
||||
choices:
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
protocols:
|
||||
description:
|
||||
- Application protocol filter.
|
||||
type: str
|
||||
quarantine:
|
||||
description:
|
||||
- Quarantine method.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- attacker
|
||||
quarantine_expiry:
|
||||
description:
|
||||
- Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m). Requires quarantine set to attacker.
|
||||
type: str
|
||||
quarantine_log:
|
||||
description:
|
||||
- Enable/disable quarantine logging.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
rate_count:
|
||||
description:
|
||||
- Count of the rate.
|
||||
type: int
|
||||
rate_duration:
|
||||
description:
|
||||
- Duration (sec) of the rate.
|
||||
type: int
|
||||
rate_mode:
|
||||
description:
|
||||
- Rate limit mode.
|
||||
type: str
|
||||
choices:
|
||||
- periodical
|
||||
- continuous
|
||||
rate_track:
|
||||
description:
|
||||
- Track the packet protocol field.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- src-ip
|
||||
- dest-ip
|
||||
- dhcp-client-mac
|
||||
- dns-domain
|
||||
risk:
|
||||
description:
|
||||
- Risk, or impact, of allowing traffic from this application to occur (1 - 5; Low, Elevated, Medium, High, and Critical).
|
||||
type: list
|
||||
suboptions:
|
||||
level:
|
||||
description:
|
||||
- Risk, or impact, of allowing traffic from this application to occur (1 - 5; Low, Elevated, Medium, High, and Critical).
|
||||
required: true
|
||||
type: int
|
||||
session_ttl:
|
||||
description:
|
||||
- Session TTL (0 = default).
|
||||
type: int
|
||||
shaper:
|
||||
description:
|
||||
- Traffic shaper. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
shaper_reverse:
|
||||
description:
|
||||
- Reverse traffic shaper. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
sub_category:
|
||||
description:
|
||||
- Application Sub-category ID list.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application sub-category ID.
|
||||
required: true
|
||||
type: int
|
||||
technology:
|
||||
description:
|
||||
- Application technology filter.
|
||||
type: str
|
||||
vendor:
|
||||
description:
|
||||
- Application vendor filter.
|
||||
type: str
|
||||
extended_log:
|
||||
description:
|
||||
- Enable/disable extended logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- List name.
|
||||
required: true
|
||||
type: str
|
||||
options:
|
||||
description:
|
||||
- Basic application protocol signatures allowed by default.
|
||||
type: str
|
||||
choices:
|
||||
- allow-dns
|
||||
- allow-icmp
|
||||
- allow-http
|
||||
- allow-ssl
|
||||
- allow-quic
|
||||
other_application_action:
|
||||
description:
|
||||
- Action for other applications.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
other_application_log:
|
||||
description:
|
||||
- Enable/disable logging for other applications.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
p2p_black_list:
|
||||
description:
|
||||
- P2P applications to be black listed.
|
||||
type: str
|
||||
choices:
|
||||
- skype
|
||||
- edonkey
|
||||
- bittorrent
|
||||
replacemsg_group:
|
||||
description:
|
||||
- Replacement message group. Source system.replacemsg-group.name.
|
||||
type: str
|
||||
unknown_application_action:
|
||||
description:
|
||||
- Pass or block traffic from unknown applications.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
unknown_application_log:
|
||||
description:
|
||||
- Enable/disable logging for unknown applications.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure application control lists.
|
||||
fortios_application_list:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
application_list:
|
||||
app_replacemsg: "disable"
|
||||
comment: "comments"
|
||||
deep_app_inspection: "disable"
|
||||
entries:
|
||||
-
|
||||
action: "pass"
|
||||
application:
|
||||
-
|
||||
id: "9"
|
||||
behavior: "<your_own_value>"
|
||||
category:
|
||||
-
|
||||
id: "12"
|
||||
id: "13"
|
||||
log: "disable"
|
||||
log_packet: "disable"
|
||||
parameters:
|
||||
-
|
||||
id: "17"
|
||||
value: "<your_own_value>"
|
||||
per_ip_shaper: "<your_own_value> (source firewall.shaper.per-ip-shaper.name)"
|
||||
popularity: "1"
|
||||
protocols: "<your_own_value>"
|
||||
quarantine: "none"
|
||||
quarantine_expiry: "<your_own_value>"
|
||||
quarantine_log: "disable"
|
||||
rate_count: "25"
|
||||
rate_duration: "26"
|
||||
rate_mode: "periodical"
|
||||
rate_track: "none"
|
||||
risk:
|
||||
-
|
||||
level: "30"
|
||||
session_ttl: "31"
|
||||
shaper: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
shaper_reverse: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
sub_category:
|
||||
-
|
||||
id: "35"
|
||||
technology: "<your_own_value>"
|
||||
vendor: "<your_own_value>"
|
||||
extended_log: "enable"
|
||||
name: "default_name_39"
|
||||
options: "allow-dns"
|
||||
other_application_action: "pass"
|
||||
other_application_log: "disable"
|
||||
p2p_black_list: "skype"
|
||||
replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)"
|
||||
unknown_application_action: "pass"
|
||||
unknown_application_log: "disable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_application_list_data(json):
|
||||
option_list = ['app_replacemsg', 'comment', 'deep_app_inspection',
|
||||
'entries', 'extended_log', 'name',
|
||||
'options', 'other_application_action', 'other_application_log',
|
||||
'p2p_black_list', 'replacemsg_group', 'unknown_application_action',
|
||||
'unknown_application_log']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def application_list(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['application_list'] and data['application_list']:
|
||||
state = data['application_list']['state']
|
||||
else:
|
||||
state = True
|
||||
application_list_data = data['application_list']
|
||||
filtered_data = underscore_to_hyphen(filter_application_list_data(application_list_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('application',
|
||||
'list',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('application',
|
||||
'list',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_application(data, fos):
|
||||
|
||||
if data['application_list']:
|
||||
resp = application_list(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application_list": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"app_replacemsg": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"deep_app_inspection": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"entries": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block", "reset"]},
|
||||
"application": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"behavior": {"required": False, "type": "str"},
|
||||
"category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"log_packet": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"parameters": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"},
|
||||
"value": {"required": False, "type": "str"}
|
||||
}},
|
||||
"per_ip_shaper": {"required": False, "type": "str"},
|
||||
"popularity": {"required": False, "type": "str",
|
||||
"choices": ["1", "2", "3",
|
||||
"4", "5"]},
|
||||
"protocols": {"required": False, "type": "str"},
|
||||
"quarantine": {"required": False, "type": "str",
|
||||
"choices": ["none", "attacker"]},
|
||||
"quarantine_expiry": {"required": False, "type": "str"},
|
||||
"quarantine_log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"rate_count": {"required": False, "type": "int"},
|
||||
"rate_duration": {"required": False, "type": "int"},
|
||||
"rate_mode": {"required": False, "type": "str",
|
||||
"choices": ["periodical", "continuous"]},
|
||||
"rate_track": {"required": False, "type": "str",
|
||||
"choices": ["none", "src-ip", "dest-ip",
|
||||
"dhcp-client-mac", "dns-domain"]},
|
||||
"risk": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"level": {"required": True, "type": "int"}
|
||||
}},
|
||||
"session_ttl": {"required": False, "type": "int"},
|
||||
"shaper": {"required": False, "type": "str"},
|
||||
"shaper_reverse": {"required": False, "type": "str"},
|
||||
"sub_category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"technology": {"required": False, "type": "str"},
|
||||
"vendor": {"required": False, "type": "str"}
|
||||
}},
|
||||
"extended_log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"options": {"required": False, "type": "str",
|
||||
"choices": ["allow-dns", "allow-icmp", "allow-http",
|
||||
"allow-ssl", "allow-quic"]},
|
||||
"other_application_action": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block"]},
|
||||
"other_application_log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"p2p_black_list": {"required": False, "type": "str",
|
||||
"choices": ["skype", "edonkey", "bittorrent"]},
|
||||
"replacemsg_group": {"required": False, "type": "str"},
|
||||
"unknown_application_action": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block"]},
|
||||
"unknown_application_log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,430 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_application_name
|
||||
short_description: Configure application signatures in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify application feature and name category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
application_name:
|
||||
description:
|
||||
- Configure application signatures.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
behavior:
|
||||
description:
|
||||
- Application behavior.
|
||||
type: str
|
||||
category:
|
||||
description:
|
||||
- Application category ID.
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- Application ID.
|
||||
type: int
|
||||
metadata:
|
||||
description:
|
||||
- Meta data.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
metaid:
|
||||
description:
|
||||
- Meta ID.
|
||||
type: int
|
||||
valueid:
|
||||
description:
|
||||
- Value ID.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Application name.
|
||||
required: true
|
||||
type: str
|
||||
parameter:
|
||||
description:
|
||||
- Application parameter name.
|
||||
type: str
|
||||
popularity:
|
||||
description:
|
||||
- Application popularity.
|
||||
type: int
|
||||
protocol:
|
||||
description:
|
||||
- Application protocol.
|
||||
type: str
|
||||
risk:
|
||||
description:
|
||||
- Application risk.
|
||||
type: int
|
||||
sub_category:
|
||||
description:
|
||||
- Application sub-category ID.
|
||||
type: int
|
||||
technology:
|
||||
description:
|
||||
- Application technology.
|
||||
type: str
|
||||
vendor:
|
||||
description:
|
||||
- Application vendor.
|
||||
type: str
|
||||
weight:
|
||||
description:
|
||||
- Application weight.
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure application signatures.
|
||||
fortios_application_name:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
application_name:
|
||||
behavior: "<your_own_value>"
|
||||
category: "4"
|
||||
id: "5"
|
||||
metadata:
|
||||
-
|
||||
id: "7"
|
||||
metaid: "8"
|
||||
valueid: "9"
|
||||
name: "default_name_10"
|
||||
parameter: "<your_own_value>"
|
||||
popularity: "12"
|
||||
protocol: "<your_own_value>"
|
||||
risk: "14"
|
||||
sub_category: "15"
|
||||
technology: "<your_own_value>"
|
||||
vendor: "<your_own_value>"
|
||||
weight: "18"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_application_name_data(json):
|
||||
option_list = ['behavior', 'category', 'id',
|
||||
'metadata', 'name', 'parameter',
|
||||
'popularity', 'protocol', 'risk',
|
||||
'sub_category', 'technology', 'vendor',
|
||||
'weight']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def application_name(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['application_name'] and data['application_name']:
|
||||
state = data['application_name']['state']
|
||||
else:
|
||||
state = True
|
||||
application_name_data = data['application_name']
|
||||
filtered_data = underscore_to_hyphen(filter_application_name_data(application_name_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('application',
|
||||
'name',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('application',
|
||||
'name',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_application(data, fos):
|
||||
|
||||
if data['application_name']:
|
||||
resp = application_name(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application_name": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"behavior": {"required": False, "type": "str"},
|
||||
"category": {"required": False, "type": "int"},
|
||||
"id": {"required": False, "type": "int"},
|
||||
"metadata": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"},
|
||||
"metaid": {"required": False, "type": "int"},
|
||||
"valueid": {"required": False, "type": "int"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"parameter": {"required": False, "type": "str"},
|
||||
"popularity": {"required": False, "type": "int"},
|
||||
"protocol": {"required": False, "type": "str"},
|
||||
"risk": {"required": False, "type": "int"},
|
||||
"sub_category": {"required": False, "type": "int"},
|
||||
"technology": {"required": False, "type": "str"},
|
||||
"vendor": {"required": False, "type": "str"},
|
||||
"weight": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,331 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_application_rule_settings
|
||||
short_description: Configure application rule settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify application feature and rule_settings category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
application_rule_settings:
|
||||
description:
|
||||
- Configure application rule settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
id:
|
||||
description:
|
||||
- Rule ID.
|
||||
required: true
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure application rule settings.
|
||||
fortios_application_rule_settings:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
application_rule_settings:
|
||||
id: "3"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_application_rule_settings_data(json):
|
||||
option_list = ['id']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def application_rule_settings(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['application_rule_settings'] and data['application_rule_settings']:
|
||||
state = data['application_rule_settings']['state']
|
||||
else:
|
||||
state = True
|
||||
application_rule_settings_data = data['application_rule_settings']
|
||||
filtered_data = underscore_to_hyphen(filter_application_rule_settings_data(application_rule_settings_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('application',
|
||||
'rule-settings',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('application',
|
||||
'rule-settings',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_application(data, fos):
|
||||
|
||||
if data['application_rule_settings']:
|
||||
resp = application_rule_settings(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application_rule_settings": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"id": {"required": True, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_application(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,439 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_authentication_rule
|
||||
short_description: Configure Authentication Rules in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify authentication feature and rule category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
authentication_rule:
|
||||
description:
|
||||
- Configure Authentication Rules.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
active_auth_method:
|
||||
description:
|
||||
- Select an active authentication method. Source authentication.scheme.name.
|
||||
type: str
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
ip_based:
|
||||
description:
|
||||
- Enable/disable IP-based authentication. Once a user authenticates all traffic from the IP address the user authenticated from is allowed.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Authentication rule name.
|
||||
required: true
|
||||
type: str
|
||||
protocol:
|
||||
description:
|
||||
- Select the protocol to use for authentication . Users connect to the FortiGate using this protocol and are asked to authenticate.
|
||||
type: str
|
||||
choices:
|
||||
- http
|
||||
- ftp
|
||||
- socks
|
||||
- ssh
|
||||
srcaddr:
|
||||
description:
|
||||
- Select an IPv4 source address from available options. Required for web proxy authentication.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr6:
|
||||
description:
|
||||
- Select an IPv6 source address. Required for web proxy authentication.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
sso_auth_method:
|
||||
description:
|
||||
- Select a single-sign on (SSO) authentication method. Source authentication.scheme.name.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this authentication rule.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
transaction_based:
|
||||
description:
|
||||
- Enable/disable transaction based authentication .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
web_auth_cookie:
|
||||
description:
|
||||
- Enable/disable Web authentication cookies .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure Authentication Rules.
|
||||
fortios_authentication_rule:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
authentication_rule:
|
||||
active_auth_method: "<your_own_value> (source authentication.scheme.name)"
|
||||
comments: "<your_own_value>"
|
||||
ip_based: "enable"
|
||||
name: "default_name_6"
|
||||
protocol: "http"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_9 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name)"
|
||||
srcaddr6:
|
||||
-
|
||||
name: "default_name_11 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
sso_auth_method: "<your_own_value> (source authentication.scheme.name)"
|
||||
status: "enable"
|
||||
transaction_based: "enable"
|
||||
web_auth_cookie: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_authentication_rule_data(json):
|
||||
option_list = ['active_auth_method', 'comments', 'ip_based',
|
||||
'name', 'protocol', 'srcaddr',
|
||||
'srcaddr6', 'sso_auth_method', 'status',
|
||||
'transaction_based', 'web_auth_cookie']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def authentication_rule(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['authentication_rule'] and data['authentication_rule']:
|
||||
state = data['authentication_rule']['state']
|
||||
else:
|
||||
state = True
|
||||
authentication_rule_data = data['authentication_rule']
|
||||
filtered_data = underscore_to_hyphen(filter_authentication_rule_data(authentication_rule_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('authentication',
|
||||
'rule',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('authentication',
|
||||
'rule',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_authentication(data, fos):
|
||||
|
||||
if data['authentication_rule']:
|
||||
resp = authentication_rule(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"authentication_rule": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"active_auth_method": {"required": False, "type": "str"},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"ip_based": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"protocol": {"required": False, "type": "str",
|
||||
"choices": ["http", "ftp", "socks",
|
||||
"ssh"]},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"sso_auth_method": {"required": False, "type": "str"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"transaction_based": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"web_auth_cookie": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_authentication(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_authentication(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,423 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_authentication_scheme
|
||||
short_description: Configure Authentication Schemes in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify authentication feature and scheme category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
authentication_scheme:
|
||||
description:
|
||||
- Configure Authentication Schemes.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
domain_controller:
|
||||
description:
|
||||
- Domain controller setting. Source user.domain-controller.name.
|
||||
type: str
|
||||
fsso_agent_for_ntlm:
|
||||
description:
|
||||
- FSSO agent to use for NTLM authentication. Source user.fsso.name.
|
||||
type: str
|
||||
fsso_guest:
|
||||
description:
|
||||
- Enable/disable user fsso-guest authentication .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
kerberos_keytab:
|
||||
description:
|
||||
- Kerberos keytab setting. Source user.krb-keytab.name.
|
||||
type: str
|
||||
method:
|
||||
description:
|
||||
- Authentication methods .
|
||||
type: str
|
||||
choices:
|
||||
- ntlm
|
||||
- basic
|
||||
- digest
|
||||
- form
|
||||
- negotiate
|
||||
- fsso
|
||||
- rsso
|
||||
- ssh-publickey
|
||||
name:
|
||||
description:
|
||||
- Authentication scheme name.
|
||||
required: true
|
||||
type: str
|
||||
negotiate_ntlm:
|
||||
description:
|
||||
- Enable/disable negotiate authentication for NTLM .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
require_tfa:
|
||||
description:
|
||||
- Enable/disable two-factor authentication .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ssh_ca:
|
||||
description:
|
||||
- SSH CA name. Source firewall.ssh.local-ca.name.
|
||||
type: str
|
||||
user_database:
|
||||
description:
|
||||
- Authentication server to contain user information; "local" (default) or "123" (for LDAP).
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Authentication server name. Source system.datasource.name user.radius.name user.tacacs+.name user.ldap.name user.group.name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure Authentication Schemes.
|
||||
fortios_authentication_scheme:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
authentication_scheme:
|
||||
domain_controller: "<your_own_value> (source user.domain-controller.name)"
|
||||
fsso_agent_for_ntlm: "<your_own_value> (source user.fsso.name)"
|
||||
fsso_guest: "enable"
|
||||
kerberos_keytab: "<your_own_value> (source user.krb-keytab.name)"
|
||||
method: "ntlm"
|
||||
name: "default_name_8"
|
||||
negotiate_ntlm: "enable"
|
||||
require_tfa: "enable"
|
||||
ssh_ca: "<your_own_value> (source firewall.ssh.local-ca.name)"
|
||||
user_database:
|
||||
-
|
||||
name: "default_name_13 (source system.datasource.name user.radius.name user.tacacs+.name user.ldap.name user.group.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_authentication_scheme_data(json):
|
||||
option_list = ['domain_controller', 'fsso_agent_for_ntlm', 'fsso_guest',
|
||||
'kerberos_keytab', 'method', 'name',
|
||||
'negotiate_ntlm', 'require_tfa', 'ssh_ca',
|
||||
'user_database']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def authentication_scheme(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['authentication_scheme'] and data['authentication_scheme']:
|
||||
state = data['authentication_scheme']['state']
|
||||
else:
|
||||
state = True
|
||||
authentication_scheme_data = data['authentication_scheme']
|
||||
filtered_data = underscore_to_hyphen(filter_authentication_scheme_data(authentication_scheme_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('authentication',
|
||||
'scheme',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('authentication',
|
||||
'scheme',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_authentication(data, fos):
|
||||
|
||||
if data['authentication_scheme']:
|
||||
resp = authentication_scheme(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"authentication_scheme": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"domain_controller": {"required": False, "type": "str"},
|
||||
"fsso_agent_for_ntlm": {"required": False, "type": "str"},
|
||||
"fsso_guest": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"kerberos_keytab": {"required": False, "type": "str"},
|
||||
"method": {"required": False, "type": "str",
|
||||
"choices": ["ntlm", "basic", "digest",
|
||||
"form", "negotiate", "fsso",
|
||||
"rsso", "ssh-publickey"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"negotiate_ntlm": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"require_tfa": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ssh_ca": {"required": False, "type": "str"},
|
||||
"user_database": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_authentication(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_authentication(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,338 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_authentication_setting
|
||||
short_description: Configure authentication setting in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify authentication feature and setting category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
authentication_setting:
|
||||
description:
|
||||
- Configure authentication setting.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
active_auth_scheme:
|
||||
description:
|
||||
- Active authentication method (scheme name). Source authentication.scheme.name.
|
||||
type: str
|
||||
captive_portal:
|
||||
description:
|
||||
- Captive portal host name. Source firewall.address.name.
|
||||
type: str
|
||||
captive_portal_ip:
|
||||
description:
|
||||
- Captive portal IP address.
|
||||
type: str
|
||||
captive_portal_ip6:
|
||||
description:
|
||||
- Captive portal IPv6 address.
|
||||
type: str
|
||||
captive_portal_port:
|
||||
description:
|
||||
- Captive portal port number (1 - 65535).
|
||||
type: int
|
||||
captive_portal_type:
|
||||
description:
|
||||
- Captive portal type.
|
||||
type: str
|
||||
choices:
|
||||
- fqdn
|
||||
- ip
|
||||
captive_portal6:
|
||||
description:
|
||||
- IPv6 captive portal host name. Source firewall.address6.name.
|
||||
type: str
|
||||
sso_auth_scheme:
|
||||
description:
|
||||
- Single-Sign-On authentication method (scheme name). Source authentication.scheme.name.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure authentication setting.
|
||||
fortios_authentication_setting:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
authentication_setting:
|
||||
active_auth_scheme: "<your_own_value> (source authentication.scheme.name)"
|
||||
captive_portal: "<your_own_value> (source firewall.address.name)"
|
||||
captive_portal_ip: "<your_own_value>"
|
||||
captive_portal_ip6: "<your_own_value>"
|
||||
captive_portal_port: "7"
|
||||
captive_portal_type: "fqdn"
|
||||
captive_portal6: "<your_own_value> (source firewall.address6.name)"
|
||||
sso_auth_scheme: "<your_own_value> (source authentication.scheme.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_authentication_setting_data(json):
|
||||
option_list = ['active_auth_scheme', 'captive_portal', 'captive_portal_ip',
|
||||
'captive_portal_ip6', 'captive_portal_port', 'captive_portal_type',
|
||||
'captive_portal6', 'sso_auth_scheme']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def authentication_setting(data, fos):
|
||||
vdom = data['vdom']
|
||||
authentication_setting_data = data['authentication_setting']
|
||||
filtered_data = underscore_to_hyphen(filter_authentication_setting_data(authentication_setting_data))
|
||||
|
||||
return fos.set('authentication',
|
||||
'setting',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_authentication(data, fos):
|
||||
|
||||
if data['authentication_setting']:
|
||||
resp = authentication_setting(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"authentication_setting": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"active_auth_scheme": {"required": False, "type": "str"},
|
||||
"captive_portal": {"required": False, "type": "str"},
|
||||
"captive_portal_ip": {"required": False, "type": "str"},
|
||||
"captive_portal_ip6": {"required": False, "type": "str"},
|
||||
"captive_portal_port": {"required": False, "type": "int"},
|
||||
"captive_portal_type": {"required": False, "type": "str",
|
||||
"choices": ["fqdn", "ip"]},
|
||||
"captive_portal6": {"required": False, "type": "str"},
|
||||
"sso_auth_scheme": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_authentication(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_authentication(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,182 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Ansible module to manage configuration on fortios devices
|
||||
# (c) 2016, Benjamin Jolivot <bjolivot@gmail.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
'status': ['preview'],
|
||||
'supported_by': 'community'}
|
||||
|
||||
|
||||
DOCUMENTATION = """
|
||||
---
|
||||
module: fortios_config
|
||||
version_added: "2.3"
|
||||
author: "Benjamin Jolivot (@bjolivot)"
|
||||
short_description: Manage config on Fortinet FortiOS firewall devices
|
||||
description:
|
||||
- This module provides management of FortiOS Devices configuration.
|
||||
extends_documentation_fragment: fortios
|
||||
options:
|
||||
src:
|
||||
description:
|
||||
- The I(src) argument provides a path to the configuration template
|
||||
to load into the remote device.
|
||||
filter:
|
||||
description:
|
||||
- Only for partial backup, you can restrict by giving expected configuration path (ex. firewall address).
|
||||
default: ""
|
||||
requirements:
|
||||
- pyFG
|
||||
"""
|
||||
|
||||
EXAMPLES = """
|
||||
- name: Backup current config
|
||||
fortios_config:
|
||||
host: 192.168.0.254
|
||||
username: admin
|
||||
password: password
|
||||
backup: yes
|
||||
|
||||
- name: Backup only address objects
|
||||
fortios_config:
|
||||
host: 192.168.0.254
|
||||
username: admin
|
||||
password: password
|
||||
backup: yes
|
||||
backup_path: /tmp/forti_backup/
|
||||
filter: "firewall address"
|
||||
|
||||
- name: Update configuration from file
|
||||
fortios_config:
|
||||
host: 192.168.0.254
|
||||
username: admin
|
||||
password: password
|
||||
src: new_configuration.conf.j2
|
||||
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
running_config:
|
||||
description: full config string
|
||||
returned: always
|
||||
type: str
|
||||
change_string:
|
||||
description: The commands really executed by the module
|
||||
returned: only if config changed
|
||||
type: str
|
||||
"""
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.network.fortios.fortios import fortios_argument_spec, fortios_required_if
|
||||
from ansible.module_utils.network.fortios.fortios import backup
|
||||
|
||||
# check for pyFG lib
|
||||
try:
|
||||
from pyFG import FortiOS, FortiConfig
|
||||
from pyFG.fortios import logger
|
||||
from pyFG.exceptions import CommandExecutionException, FailedCommit, ForcedCommit
|
||||
HAS_PYFG = True
|
||||
except Exception:
|
||||
HAS_PYFG = False
|
||||
|
||||
|
||||
# some blocks don't support update, so remove them
|
||||
NOT_UPDATABLE_CONFIG_OBJECTS = [
|
||||
"vpn certificate local",
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = dict(
|
||||
src=dict(type='str', default=None),
|
||||
filter=dict(type='str', default=""),
|
||||
)
|
||||
|
||||
argument_spec.update(fortios_argument_spec)
|
||||
|
||||
required_if = fortios_required_if
|
||||
|
||||
module = AnsibleModule(
|
||||
argument_spec=argument_spec,
|
||||
supports_check_mode=True,
|
||||
required_if=required_if,
|
||||
)
|
||||
|
||||
result = dict(changed=False)
|
||||
|
||||
# fail if pyFG not present
|
||||
if not HAS_PYFG:
|
||||
module.fail_json(msg='Could not import the python library pyFG required by this module')
|
||||
|
||||
# define device
|
||||
f = FortiOS(module.params['host'],
|
||||
username=module.params['username'],
|
||||
password=module.params['password'],
|
||||
timeout=module.params['timeout'],
|
||||
vdom=module.params['vdom'])
|
||||
|
||||
# connect
|
||||
try:
|
||||
f.open()
|
||||
except Exception:
|
||||
module.fail_json(msg='Error connecting device')
|
||||
|
||||
# get config
|
||||
try:
|
||||
f.load_config(path=module.params['filter'])
|
||||
result['running_config'] = f.running_config.to_text()
|
||||
|
||||
except Exception:
|
||||
module.fail_json(msg='Error reading running config')
|
||||
|
||||
# backup config
|
||||
if module.params['backup']:
|
||||
backup(module, f.running_config.to_text())
|
||||
|
||||
# update config
|
||||
if module.params['src'] is not None:
|
||||
# store config in str
|
||||
try:
|
||||
conf_str = module.params['src']
|
||||
f.load_config(in_candidate=True, config_text=conf_str)
|
||||
except Exception:
|
||||
module.fail_json(msg="Can't open configuration file, or configuration invalid")
|
||||
|
||||
# get updates lines
|
||||
change_string = f.compare_config()
|
||||
|
||||
# remove not updatable parts
|
||||
c = FortiConfig()
|
||||
c.parse_config_output(change_string)
|
||||
|
||||
for o in NOT_UPDATABLE_CONFIG_OBJECTS:
|
||||
c.del_block(o)
|
||||
|
||||
change_string = c.to_text()
|
||||
|
||||
if change_string != "":
|
||||
result['change_string'] = change_string
|
||||
result['changed'] = True
|
||||
|
||||
# Commit if not check mode
|
||||
if module.check_mode is False and change_string != "":
|
||||
try:
|
||||
f.commit(change_string)
|
||||
except CommandExecutionException as e:
|
||||
module.fail_json(msg="Unable to execute command, check your args, the error was {0}".format(e.message))
|
||||
except FailedCommit as e:
|
||||
module.fail_json(msg="Unable to commit, check your args, the error was {0}".format(e.message))
|
||||
except ForcedCommit as e:
|
||||
module.fail_json(msg="Failed to force commit, check your args, the error was {0}".format(e.message))
|
||||
|
||||
module.exit_json(**result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,457 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dlp_filepattern
|
||||
short_description: Configure file patterns used by DLP blocking in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dlp feature and filepattern category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
dlp_filepattern:
|
||||
description:
|
||||
- Configure file patterns used by DLP blocking.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Optional comments.
|
||||
type: str
|
||||
entries:
|
||||
description:
|
||||
- Configure file patterns used by DLP blocking.
|
||||
type: list
|
||||
suboptions:
|
||||
file_type:
|
||||
description:
|
||||
- Select a file type.
|
||||
type: str
|
||||
choices:
|
||||
- 7z
|
||||
- arj
|
||||
- cab
|
||||
- lzh
|
||||
- rar
|
||||
- tar
|
||||
- zip
|
||||
- bzip
|
||||
- gzip
|
||||
- bzip2
|
||||
- xz
|
||||
- bat
|
||||
- msc
|
||||
- uue
|
||||
- mime
|
||||
- base64
|
||||
- binhex
|
||||
- elf
|
||||
- exe
|
||||
- hta
|
||||
- html
|
||||
- jad
|
||||
- class
|
||||
- cod
|
||||
- javascript
|
||||
- msoffice
|
||||
- msofficex
|
||||
- fsg
|
||||
- upx
|
||||
- petite
|
||||
- aspack
|
||||
- sis
|
||||
- hlp
|
||||
- activemime
|
||||
- jpeg
|
||||
- gif
|
||||
- tiff
|
||||
- png
|
||||
- bmp
|
||||
- ignored
|
||||
- unknown
|
||||
- mpeg
|
||||
- mov
|
||||
- mp3
|
||||
- wma
|
||||
- wav
|
||||
- pdf
|
||||
- avi
|
||||
- rm
|
||||
- torrent
|
||||
- hibun
|
||||
- msi
|
||||
- mach-o
|
||||
- dmg
|
||||
- .net
|
||||
- xar
|
||||
- chm
|
||||
- iso
|
||||
- crx
|
||||
filter_type:
|
||||
description:
|
||||
- Filter by file name pattern or by file type.
|
||||
type: str
|
||||
choices:
|
||||
- pattern
|
||||
- type
|
||||
pattern:
|
||||
description:
|
||||
- Add a file name pattern.
|
||||
required: true
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Name of table containing the file pattern list.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure file patterns used by DLP blocking.
|
||||
fortios_dlp_filepattern:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
dlp_filepattern:
|
||||
comment: "Optional comments."
|
||||
entries:
|
||||
-
|
||||
file_type: "7z"
|
||||
filter_type: "pattern"
|
||||
pattern: "<your_own_value>"
|
||||
id: "8"
|
||||
name: "default_name_9"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dlp_filepattern_data(json):
|
||||
option_list = ['comment', 'entries', 'id',
|
||||
'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dlp_filepattern(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['dlp_filepattern'] and data['dlp_filepattern']:
|
||||
state = data['dlp_filepattern']['state']
|
||||
else:
|
||||
state = True
|
||||
dlp_filepattern_data = data['dlp_filepattern']
|
||||
filtered_data = underscore_to_hyphen(filter_dlp_filepattern_data(dlp_filepattern_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('dlp',
|
||||
'filepattern',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('dlp',
|
||||
'filepattern',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dlp(data, fos):
|
||||
|
||||
if data['dlp_filepattern']:
|
||||
resp = dlp_filepattern(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dlp_filepattern": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"entries": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"file_type": {"required": False, "type": "str",
|
||||
"choices": ["7z", "arj", "cab",
|
||||
"lzh", "rar", "tar",
|
||||
"zip", "bzip", "gzip",
|
||||
"bzip2", "xz", "bat",
|
||||
"msc", "uue", "mime",
|
||||
"base64", "binhex", "elf",
|
||||
"exe", "hta", "html",
|
||||
"jad", "class", "cod",
|
||||
"javascript", "msoffice", "msofficex",
|
||||
"fsg", "upx", "petite",
|
||||
"aspack", "sis", "hlp",
|
||||
"activemime", "jpeg", "gif",
|
||||
"tiff", "png", "bmp",
|
||||
"ignored", "unknown", "mpeg",
|
||||
"mov", "mp3", "wma",
|
||||
"wav", "pdf", "avi",
|
||||
"rm", "torrent", "hibun",
|
||||
"msi", "mach-o", "dmg",
|
||||
".net", "xar", "chm",
|
||||
"iso", "crx"]},
|
||||
"filter_type": {"required": False, "type": "str",
|
||||
"choices": ["pattern", "type"]},
|
||||
"pattern": {"required": True, "type": "str"}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"name": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,481 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dlp_fp_doc_source
|
||||
short_description: Create a DLP fingerprint database by allowing the FortiGate to access a file server containing files from which to create fingerprints in
|
||||
Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dlp feature and fp_doc_source category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
dlp_fp_doc_source:
|
||||
description:
|
||||
- Create a DLP fingerprint database by allowing the FortiGate to access a file server containing files from which to create fingerprints.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
date:
|
||||
description:
|
||||
- Day of the month on which to scan the server (1 - 31).
|
||||
type: int
|
||||
file_path:
|
||||
description:
|
||||
- Path on the server to the fingerprint files (max 119 characters).
|
||||
type: str
|
||||
file_pattern:
|
||||
description:
|
||||
- Files matching this pattern on the server are fingerprinted. Optionally use the * and ? wildcards.
|
||||
type: str
|
||||
keep_modified:
|
||||
description:
|
||||
- Enable so that when a file is changed on the server the FortiGate keeps the old fingerprint and adds a new fingerprint to the database.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Name of the DLP fingerprint database.
|
||||
required: true
|
||||
type: str
|
||||
password:
|
||||
description:
|
||||
- Password required to log into the file server.
|
||||
type: str
|
||||
period:
|
||||
description:
|
||||
- Frequency for which the FortiGate checks the server for new or changed files.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- daily
|
||||
- weekly
|
||||
- monthly
|
||||
remove_deleted:
|
||||
description:
|
||||
- Enable to keep the fingerprint database up to date when a file is deleted from the server.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
scan_on_creation:
|
||||
description:
|
||||
- Enable to keep the fingerprint database up to date when a file is added or changed on the server.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
scan_subdirectories:
|
||||
description:
|
||||
- Enable/disable scanning subdirectories to find files to create fingerprints from.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
sensitivity:
|
||||
description:
|
||||
- Select a sensitivity or threat level for matches with this fingerprint database. Add sensitivities using fp-sensitivity. Source dlp
|
||||
.fp-sensitivity.name.
|
||||
type: str
|
||||
server:
|
||||
description:
|
||||
- IPv4 or IPv6 address of the server.
|
||||
type: str
|
||||
server_type:
|
||||
description:
|
||||
- Protocol used to communicate with the file server. Currently only Samba (SMB) servers are supported.
|
||||
type: str
|
||||
choices:
|
||||
- samba
|
||||
tod_hour:
|
||||
description:
|
||||
- Hour of the day on which to scan the server (0 - 23).
|
||||
type: int
|
||||
tod_min:
|
||||
description:
|
||||
- Minute of the hour on which to scan the server (0 - 59).
|
||||
type: int
|
||||
username:
|
||||
description:
|
||||
- User name required to log into the file server.
|
||||
type: str
|
||||
vdom:
|
||||
description:
|
||||
- Select the VDOM that can communicate with the file server.
|
||||
type: str
|
||||
choices:
|
||||
- mgmt
|
||||
- current
|
||||
weekday:
|
||||
description:
|
||||
- Day of the week on which to scan the server.
|
||||
type: str
|
||||
choices:
|
||||
- sunday
|
||||
- monday
|
||||
- tuesday
|
||||
- wednesday
|
||||
- thursday
|
||||
- friday
|
||||
- saturday
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Create a DLP fingerprint database by allowing the FortiGate to access a file server containing files from which to create fingerprints.
|
||||
fortios_dlp_fp_doc_source:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
dlp_fp_doc_source:
|
||||
date: "3"
|
||||
file_path: "<your_own_value>"
|
||||
file_pattern: "<your_own_value>"
|
||||
keep_modified: "enable"
|
||||
name: "default_name_7"
|
||||
password: "<your_own_value>"
|
||||
period: "none"
|
||||
remove_deleted: "enable"
|
||||
scan_on_creation: "enable"
|
||||
scan_subdirectories: "enable"
|
||||
sensitivity: "<your_own_value> (source dlp.fp-sensitivity.name)"
|
||||
server: "192.168.100.40"
|
||||
server_type: "samba"
|
||||
tod_hour: "16"
|
||||
tod_min: "17"
|
||||
username: "<your_own_value>"
|
||||
vdom: "mgmt"
|
||||
weekday: "sunday"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dlp_fp_doc_source_data(json):
|
||||
option_list = ['date', 'file_path', 'file_pattern',
|
||||
'keep_modified', 'name', 'password',
|
||||
'period', 'remove_deleted', 'scan_on_creation',
|
||||
'scan_subdirectories', 'sensitivity', 'server',
|
||||
'server_type', 'tod_hour', 'tod_min',
|
||||
'username', 'vdom', 'weekday']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dlp_fp_doc_source(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['dlp_fp_doc_source'] and data['dlp_fp_doc_source']:
|
||||
state = data['dlp_fp_doc_source']['state']
|
||||
else:
|
||||
state = True
|
||||
dlp_fp_doc_source_data = data['dlp_fp_doc_source']
|
||||
filtered_data = underscore_to_hyphen(filter_dlp_fp_doc_source_data(dlp_fp_doc_source_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('dlp',
|
||||
'fp-doc-source',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('dlp',
|
||||
'fp-doc-source',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dlp(data, fos):
|
||||
|
||||
if data['dlp_fp_doc_source']:
|
||||
resp = dlp_fp_doc_source(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dlp_fp_doc_source": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"date": {"required": False, "type": "int"},
|
||||
"file_path": {"required": False, "type": "str"},
|
||||
"file_pattern": {"required": False, "type": "str"},
|
||||
"keep_modified": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"password": {"required": False, "type": "str"},
|
||||
"period": {"required": False, "type": "str",
|
||||
"choices": ["none", "daily", "weekly",
|
||||
"monthly"]},
|
||||
"remove_deleted": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"scan_on_creation": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"scan_subdirectories": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"sensitivity": {"required": False, "type": "str"},
|
||||
"server": {"required": False, "type": "str"},
|
||||
"server_type": {"required": False, "type": "str",
|
||||
"choices": ["samba"]},
|
||||
"tod_hour": {"required": False, "type": "int"},
|
||||
"tod_min": {"required": False, "type": "int"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"vdom": {"required": False, "type": "str",
|
||||
"choices": ["mgmt", "current"]},
|
||||
"weekday": {"required": False, "type": "str",
|
||||
"choices": ["sunday", "monday", "tuesday",
|
||||
"wednesday", "thursday", "friday",
|
||||
"saturday"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,332 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dlp_fp_sensitivity
|
||||
short_description: Create self-explanatory DLP sensitivity levels to be used when setting sensitivity under config fp-doc-source in Fortinet's FortiOS and
|
||||
FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dlp feature and fp_sensitivity category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
dlp_fp_sensitivity:
|
||||
description:
|
||||
- Create self-explanatory DLP sensitivity levels to be used when setting sensitivity under config fp-doc-source.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
name:
|
||||
description:
|
||||
- DLP Sensitivity Levels.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Create self-explanatory DLP sensitivity levels to be used when setting sensitivity under config fp-doc-source.
|
||||
fortios_dlp_fp_sensitivity:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
dlp_fp_sensitivity:
|
||||
name: "default_name_3"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dlp_fp_sensitivity_data(json):
|
||||
option_list = ['name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dlp_fp_sensitivity(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['dlp_fp_sensitivity'] and data['dlp_fp_sensitivity']:
|
||||
state = data['dlp_fp_sensitivity']['state']
|
||||
else:
|
||||
state = True
|
||||
dlp_fp_sensitivity_data = data['dlp_fp_sensitivity']
|
||||
filtered_data = underscore_to_hyphen(filter_dlp_fp_sensitivity_data(dlp_fp_sensitivity_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('dlp',
|
||||
'fp-sensitivity',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('dlp',
|
||||
'fp-sensitivity',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dlp(data, fos):
|
||||
|
||||
if data['dlp_fp_sensitivity']:
|
||||
resp = dlp_fp_sensitivity(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dlp_fp_sensitivity": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"name": {"required": True, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,602 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dlp_sensor
|
||||
short_description: Configure DLP sensors in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dlp feature and sensor category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
dlp_sensor:
|
||||
description:
|
||||
- Configure DLP sensors.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dlp_log:
|
||||
description:
|
||||
- Enable/disable DLP logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
extended_log:
|
||||
description:
|
||||
- Enable/disable extended logging for data leak prevention.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
filter:
|
||||
description:
|
||||
- Set up DLP filters for this sensor.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Action to take with content that this DLP sensor matches.
|
||||
type: str
|
||||
choices:
|
||||
- allow
|
||||
- log-only
|
||||
- block
|
||||
- quarantine-ip
|
||||
archive:
|
||||
description:
|
||||
- Enable/disable DLP archiving.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
company_identifier:
|
||||
description:
|
||||
- Enter a company identifier watermark to match. Only watermarks that your company has placed on the files are matched.
|
||||
type: str
|
||||
expiry:
|
||||
description:
|
||||
- Quarantine duration in days, hours, minutes format (dddhhmm).
|
||||
type: str
|
||||
file_size:
|
||||
description:
|
||||
- Match files this size or larger (0 - 4294967295 kbytes).
|
||||
type: int
|
||||
file_type:
|
||||
description:
|
||||
- Select the number of a DLP file pattern table to match. Source dlp.filepattern.id.
|
||||
type: int
|
||||
filter_by:
|
||||
description:
|
||||
- Select the type of content to match.
|
||||
type: str
|
||||
choices:
|
||||
- credit-card
|
||||
- ssn
|
||||
- regexp
|
||||
- file-type
|
||||
- file-size
|
||||
- fingerprint
|
||||
- watermark
|
||||
- encrypted
|
||||
fp_sensitivity:
|
||||
description:
|
||||
- Select a DLP file pattern sensitivity to match.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Select a DLP sensitivity. Source dlp.fp-sensitivity.name.
|
||||
required: true
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
match_percentage:
|
||||
description:
|
||||
- Percentage of fingerprints in the fingerprint databases designated with the selected fp-sensitivity to match.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Filter name.
|
||||
type: str
|
||||
proto:
|
||||
description:
|
||||
- Check messages or files over one or more of these protocols.
|
||||
type: str
|
||||
choices:
|
||||
- smtp
|
||||
- pop3
|
||||
- imap
|
||||
- http-get
|
||||
- http-post
|
||||
- ftp
|
||||
- nntp
|
||||
- mapi
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
regexp:
|
||||
description:
|
||||
- Enter a regular expression to match (max. 255 characters).
|
||||
type: str
|
||||
severity:
|
||||
description:
|
||||
- Select the severity or threat level that matches this filter.
|
||||
type: str
|
||||
choices:
|
||||
- info
|
||||
- low
|
||||
- medium
|
||||
- high
|
||||
- critical
|
||||
type:
|
||||
description:
|
||||
- Select whether to check the content of messages (an email message) or files (downloaded files or email attachments).
|
||||
type: str
|
||||
choices:
|
||||
- file
|
||||
- message
|
||||
flow_based:
|
||||
description:
|
||||
- Enable/disable flow-based DLP.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
full_archive_proto:
|
||||
description:
|
||||
- Protocols to always content archive.
|
||||
type: str
|
||||
choices:
|
||||
- smtp
|
||||
- pop3
|
||||
- imap
|
||||
- http-get
|
||||
- http-post
|
||||
- ftp
|
||||
- nntp
|
||||
- mapi
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
nac_quar_log:
|
||||
description:
|
||||
- Enable/disable NAC quarantine logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Name of the DLP sensor.
|
||||
required: true
|
||||
type: str
|
||||
options:
|
||||
description:
|
||||
- Configure DLP options.
|
||||
type: str
|
||||
replacemsg_group:
|
||||
description:
|
||||
- Replacement message group used by this DLP sensor. Source system.replacemsg-group.name.
|
||||
type: str
|
||||
summary_proto:
|
||||
description:
|
||||
- Protocols to always log summary.
|
||||
type: str
|
||||
choices:
|
||||
- smtp
|
||||
- pop3
|
||||
- imap
|
||||
- http-get
|
||||
- http-post
|
||||
- ftp
|
||||
- nntp
|
||||
- mapi
|
||||
- mm1
|
||||
- mm3
|
||||
- mm4
|
||||
- mm7
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure DLP sensors.
|
||||
fortios_dlp_sensor:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
dlp_sensor:
|
||||
comment: "Comment."
|
||||
dlp_log: "enable"
|
||||
extended_log: "enable"
|
||||
filter:
|
||||
-
|
||||
action: "allow"
|
||||
archive: "disable"
|
||||
company_identifier: "myId_9"
|
||||
expiry: "<your_own_value>"
|
||||
file_size: "11"
|
||||
file_type: "12 (source dlp.filepattern.id)"
|
||||
filter_by: "credit-card"
|
||||
fp_sensitivity:
|
||||
-
|
||||
name: "default_name_15 (source dlp.fp-sensitivity.name)"
|
||||
id: "16"
|
||||
match_percentage: "17"
|
||||
name: "default_name_18"
|
||||
proto: "smtp"
|
||||
regexp: "<your_own_value>"
|
||||
severity: "info"
|
||||
type: "file"
|
||||
flow_based: "enable"
|
||||
full_archive_proto: "smtp"
|
||||
nac_quar_log: "enable"
|
||||
name: "default_name_26"
|
||||
options: "<your_own_value>"
|
||||
replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)"
|
||||
summary_proto: "smtp"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dlp_sensor_data(json):
|
||||
option_list = ['comment', 'dlp_log', 'extended_log',
|
||||
'filter', 'flow_based', 'full_archive_proto',
|
||||
'nac_quar_log', 'name', 'options',
|
||||
'replacemsg_group', 'summary_proto']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dlp_sensor(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['dlp_sensor'] and data['dlp_sensor']:
|
||||
state = data['dlp_sensor']['state']
|
||||
else:
|
||||
state = True
|
||||
dlp_sensor_data = data['dlp_sensor']
|
||||
filtered_data = underscore_to_hyphen(filter_dlp_sensor_data(dlp_sensor_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('dlp',
|
||||
'sensor',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('dlp',
|
||||
'sensor',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dlp(data, fos):
|
||||
|
||||
if data['dlp_sensor']:
|
||||
resp = dlp_sensor(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dlp_sensor": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"dlp_log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"extended_log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"filter": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["allow", "log-only", "block",
|
||||
"quarantine-ip"]},
|
||||
"archive": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"company_identifier": {"required": False, "type": "str"},
|
||||
"expiry": {"required": False, "type": "str"},
|
||||
"file_size": {"required": False, "type": "int"},
|
||||
"file_type": {"required": False, "type": "int"},
|
||||
"filter_by": {"required": False, "type": "str",
|
||||
"choices": ["credit-card", "ssn", "regexp",
|
||||
"file-type", "file-size", "fingerprint",
|
||||
"watermark", "encrypted"]},
|
||||
"fp_sensitivity": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"match_percentage": {"required": False, "type": "int"},
|
||||
"name": {"required": False, "type": "str"},
|
||||
"proto": {"required": False, "type": "str",
|
||||
"choices": ["smtp", "pop3", "imap",
|
||||
"http-get", "http-post", "ftp",
|
||||
"nntp", "mapi", "mm1",
|
||||
"mm3", "mm4", "mm7"]},
|
||||
"regexp": {"required": False, "type": "str"},
|
||||
"severity": {"required": False, "type": "str",
|
||||
"choices": ["info", "low", "medium",
|
||||
"high", "critical"]},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["file", "message"]}
|
||||
}},
|
||||
"flow_based": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"full_archive_proto": {"required": False, "type": "str",
|
||||
"choices": ["smtp", "pop3", "imap",
|
||||
"http-get", "http-post", "ftp",
|
||||
"nntp", "mapi", "mm1",
|
||||
"mm3", "mm4", "mm7"]},
|
||||
"nac_quar_log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"options": {"required": False, "type": "str"},
|
||||
"replacemsg_group": {"required": False, "type": "str"},
|
||||
"summary_proto": {"required": False, "type": "str",
|
||||
"choices": ["smtp", "pop3", "imap",
|
||||
"http-get", "http-post", "ftp",
|
||||
"nntp", "mapi", "mm1",
|
||||
"mm3", "mm4", "mm7"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,320 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dlp_settings
|
||||
short_description: Designate logical storage for DLP fingerprint database in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dlp feature and settings category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
dlp_settings:
|
||||
description:
|
||||
- Designate logical storage for DLP fingerprint database.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
cache_mem_percent:
|
||||
description:
|
||||
- Maximum percentage of available memory allocated to caching (1 - 15%).
|
||||
type: int
|
||||
chunk_size:
|
||||
description:
|
||||
- Maximum fingerprint chunk size. **Changing will flush the entire database**.
|
||||
type: int
|
||||
db_mode:
|
||||
description:
|
||||
- Behaviour when the maximum size is reached.
|
||||
type: str
|
||||
choices:
|
||||
- stop-adding
|
||||
- remove-modified-then-oldest
|
||||
- remove-oldest
|
||||
size:
|
||||
description:
|
||||
- Maximum total size of files within the storage (MB).
|
||||
type: int
|
||||
storage_device:
|
||||
description:
|
||||
- Storage device name. Source system.storage.name.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Designate logical storage for DLP fingerprint database.
|
||||
fortios_dlp_settings:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
dlp_settings:
|
||||
cache_mem_percent: "3"
|
||||
chunk_size: "4"
|
||||
db_mode: "stop-adding"
|
||||
size: "6"
|
||||
storage_device: "<your_own_value> (source system.storage.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dlp_settings_data(json):
|
||||
option_list = ['cache_mem_percent', 'chunk_size', 'db_mode',
|
||||
'size', 'storage_device']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dlp_settings(data, fos):
|
||||
vdom = data['vdom']
|
||||
dlp_settings_data = data['dlp_settings']
|
||||
filtered_data = underscore_to_hyphen(filter_dlp_settings_data(dlp_settings_data))
|
||||
|
||||
return fos.set('dlp',
|
||||
'settings',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dlp(data, fos):
|
||||
|
||||
if data['dlp_settings']:
|
||||
resp = dlp_settings(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"dlp_settings": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"cache_mem_percent": {"required": False, "type": "int"},
|
||||
"chunk_size": {"required": False, "type": "int"},
|
||||
"db_mode": {"required": False, "type": "str",
|
||||
"choices": ["stop-adding", "remove-modified-then-oldest", "remove-oldest"]},
|
||||
"size": {"required": False, "type": "int"},
|
||||
"storage_device": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dlp(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,399 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dnsfilter_domain_filter
|
||||
short_description: Configure DNS domain filters in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dnsfilter feature and domain_filter category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
dnsfilter_domain_filter:
|
||||
description:
|
||||
- Configure DNS domain filters.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Optional comments.
|
||||
type: str
|
||||
entries:
|
||||
description:
|
||||
- DNS domain filter entries.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Action to take for domain filter matches.
|
||||
type: str
|
||||
choices:
|
||||
- block
|
||||
- allow
|
||||
- monitor
|
||||
domain:
|
||||
description:
|
||||
- Domain entries to be filtered.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Id.
|
||||
required: true
|
||||
type: int
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this domain filter.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
type:
|
||||
description:
|
||||
- DNS domain filter type.
|
||||
type: str
|
||||
choices:
|
||||
- simple
|
||||
- regex
|
||||
- wildcard
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Name of table.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure DNS domain filters.
|
||||
fortios_dnsfilter_domain_filter:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
dnsfilter_domain_filter:
|
||||
comment: "Optional comments."
|
||||
entries:
|
||||
-
|
||||
action: "block"
|
||||
domain: "<your_own_value>"
|
||||
id: "7"
|
||||
status: "enable"
|
||||
type: "simple"
|
||||
id: "10"
|
||||
name: "default_name_11"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dnsfilter_domain_filter_data(json):
|
||||
option_list = ['comment', 'entries', 'id',
|
||||
'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dnsfilter_domain_filter(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['dnsfilter_domain_filter'] and data['dnsfilter_domain_filter']:
|
||||
state = data['dnsfilter_domain_filter']['state']
|
||||
else:
|
||||
state = True
|
||||
dnsfilter_domain_filter_data = data['dnsfilter_domain_filter']
|
||||
filtered_data = underscore_to_hyphen(filter_dnsfilter_domain_filter_data(dnsfilter_domain_filter_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('dnsfilter',
|
||||
'domain-filter',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('dnsfilter',
|
||||
'domain-filter',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dnsfilter(data, fos):
|
||||
|
||||
if data['dnsfilter_domain_filter']:
|
||||
resp = dnsfilter_domain_filter(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dnsfilter_domain_filter": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"entries": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["block", "allow", "monitor"]},
|
||||
"domain": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["simple", "regex", "wildcard"]}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"name": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dnsfilter(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dnsfilter(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,511 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_dnsfilter_profile
|
||||
short_description: Configure DNS domain filter profiles in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify dnsfilter feature and profile category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
dnsfilter_profile:
|
||||
description:
|
||||
- Configure DNS domain filter profiles.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
block_action:
|
||||
description:
|
||||
- Action to take for blocked domains.
|
||||
type: str
|
||||
choices:
|
||||
- block
|
||||
- redirect
|
||||
block_botnet:
|
||||
description:
|
||||
- Enable/disable blocking botnet C&C DNS lookups.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
domain_filter:
|
||||
description:
|
||||
- Domain filter settings.
|
||||
type: dict
|
||||
suboptions:
|
||||
domain_filter_table:
|
||||
description:
|
||||
- DNS domain filter table ID. Source dnsfilter.domain-filter.id.
|
||||
type: int
|
||||
external_ip_blocklist:
|
||||
description:
|
||||
- One or more external IP block lists.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- External domain block list name. Source system.external-resource.name.
|
||||
required: true
|
||||
type: str
|
||||
ftgd_dns:
|
||||
description:
|
||||
- FortiGuard DNS Filter settings.
|
||||
type: dict
|
||||
suboptions:
|
||||
filters:
|
||||
description:
|
||||
- FortiGuard DNS domain filters.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Action to take for DNS requests matching the category.
|
||||
type: str
|
||||
choices:
|
||||
- block
|
||||
- monitor
|
||||
category:
|
||||
description:
|
||||
- Category number.
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- ID number.
|
||||
required: true
|
||||
type: int
|
||||
log:
|
||||
description:
|
||||
- Enable/disable DNS filter logging for this DNS profile.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
options:
|
||||
description:
|
||||
- FortiGuard DNS filter options.
|
||||
type: str
|
||||
choices:
|
||||
- error-allow
|
||||
- ftgd-disable
|
||||
log_all_domain:
|
||||
description:
|
||||
- Enable/disable logging of all domains visited (detailed DNS logging).
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Profile name.
|
||||
required: true
|
||||
type: str
|
||||
redirect_portal:
|
||||
description:
|
||||
- IP address of the SDNS redirect portal.
|
||||
type: str
|
||||
safe_search:
|
||||
description:
|
||||
- Enable/disable Google, Bing, and YouTube safe search.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
sdns_domain_log:
|
||||
description:
|
||||
- Enable/disable domain filtering and botnet domain logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
sdns_ftgd_err_log:
|
||||
description:
|
||||
- Enable/disable FortiGuard SDNS rating error logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
youtube_restrict:
|
||||
description:
|
||||
- Set safe search for YouTube restriction level.
|
||||
type: str
|
||||
choices:
|
||||
- strict
|
||||
- moderate
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure DNS domain filter profiles.
|
||||
fortios_dnsfilter_profile:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
dnsfilter_profile:
|
||||
block_action: "block"
|
||||
block_botnet: "disable"
|
||||
comment: "Comment."
|
||||
domain_filter:
|
||||
domain_filter_table: "7 (source dnsfilter.domain-filter.id)"
|
||||
external_ip_blocklist:
|
||||
-
|
||||
name: "default_name_9 (source system.external-resource.name)"
|
||||
ftgd_dns:
|
||||
filters:
|
||||
-
|
||||
action: "block"
|
||||
category: "13"
|
||||
id: "14"
|
||||
log: "enable"
|
||||
options: "error-allow"
|
||||
log_all_domain: "enable"
|
||||
name: "default_name_18"
|
||||
redirect_portal: "<your_own_value>"
|
||||
safe_search: "disable"
|
||||
sdns_domain_log: "enable"
|
||||
sdns_ftgd_err_log: "enable"
|
||||
youtube_restrict: "strict"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_dnsfilter_profile_data(json):
|
||||
option_list = ['block_action', 'block_botnet', 'comment',
|
||||
'domain_filter', 'external_ip_blocklist', 'ftgd_dns',
|
||||
'log_all_domain', 'name', 'redirect_portal',
|
||||
'safe_search', 'sdns_domain_log', 'sdns_ftgd_err_log',
|
||||
'youtube_restrict']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def dnsfilter_profile(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['dnsfilter_profile'] and data['dnsfilter_profile']:
|
||||
state = data['dnsfilter_profile']['state']
|
||||
else:
|
||||
state = True
|
||||
dnsfilter_profile_data = data['dnsfilter_profile']
|
||||
filtered_data = underscore_to_hyphen(filter_dnsfilter_profile_data(dnsfilter_profile_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('dnsfilter',
|
||||
'profile',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('dnsfilter',
|
||||
'profile',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_dnsfilter(data, fos):
|
||||
|
||||
if data['dnsfilter_profile']:
|
||||
resp = dnsfilter_profile(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dnsfilter_profile": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"block_action": {"required": False, "type": "str",
|
||||
"choices": ["block", "redirect"]},
|
||||
"block_botnet": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"domain_filter": {"required": False, "type": "dict",
|
||||
"options": {
|
||||
"domain_filter_table": {"required": False, "type": "int"}
|
||||
}},
|
||||
"external_ip_blocklist": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"ftgd_dns": {"required": False, "type": "dict",
|
||||
"options": {
|
||||
"filters": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["block", "monitor"]},
|
||||
"category": {"required": False, "type": "int"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
}},
|
||||
"options": {"required": False, "type": "str",
|
||||
"choices": ["error-allow", "ftgd-disable"]}
|
||||
}},
|
||||
"log_all_domain": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"redirect_portal": {"required": False, "type": "str"},
|
||||
"safe_search": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"sdns_domain_log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"sdns_ftgd_err_log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"youtube_restrict": {"required": False, "type": "str",
|
||||
"choices": ["strict", "moderate"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_dnsfilter(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_dnsfilter(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,362 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_endpoint_control_client
|
||||
short_description: Configure endpoint control client lists in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify endpoint_control feature and client category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
endpoint_control_client:
|
||||
description:
|
||||
- Configure endpoint control client lists.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
ad_groups:
|
||||
description:
|
||||
- Endpoint client AD logon groups.
|
||||
type: str
|
||||
ftcl_uid:
|
||||
description:
|
||||
- Endpoint FortiClient UID.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Endpoint client ID.
|
||||
required: true
|
||||
type: int
|
||||
info:
|
||||
description:
|
||||
- Endpoint client information.
|
||||
type: str
|
||||
src_ip:
|
||||
description:
|
||||
- Endpoint client IP address.
|
||||
type: str
|
||||
src_mac:
|
||||
description:
|
||||
- Endpoint client MAC address.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure endpoint control client lists.
|
||||
fortios_endpoint_control_client:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
endpoint_control_client:
|
||||
ad_groups: "<your_own_value>"
|
||||
ftcl_uid: "<your_own_value>"
|
||||
id: "5"
|
||||
info: "<your_own_value>"
|
||||
src_ip: "<your_own_value>"
|
||||
src_mac: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_endpoint_control_client_data(json):
|
||||
option_list = ['ad_groups', 'ftcl_uid', 'id',
|
||||
'info', 'src_ip', 'src_mac']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def endpoint_control_client(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['endpoint_control_client'] and data['endpoint_control_client']:
|
||||
state = data['endpoint_control_client']['state']
|
||||
else:
|
||||
state = True
|
||||
endpoint_control_client_data = data['endpoint_control_client']
|
||||
filtered_data = underscore_to_hyphen(filter_endpoint_control_client_data(endpoint_control_client_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('endpoint-control',
|
||||
'client',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('endpoint-control',
|
||||
'client',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_endpoint_control(data, fos):
|
||||
|
||||
if data['endpoint_control_client']:
|
||||
resp = endpoint_control_client(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"endpoint_control_client": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"ad_groups": {"required": False, "type": "str"},
|
||||
"ftcl_uid": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"info": {"required": False, "type": "str"},
|
||||
"src_ip": {"required": False, "type": "str"},
|
||||
"src_mac": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,396 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_endpoint_control_forticlient_ems
|
||||
short_description: Configure FortiClient Enterprise Management Server (EMS) entries in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify endpoint_control feature and forticlient_ems category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
endpoint_control_forticlient_ems:
|
||||
description:
|
||||
- Configure FortiClient Enterprise Management Server (EMS) entries.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
address:
|
||||
description:
|
||||
- Firewall address name. Source firewall.address.name.
|
||||
type: str
|
||||
admin_password:
|
||||
description:
|
||||
- FortiClient EMS admin password.
|
||||
type: str
|
||||
admin_type:
|
||||
description:
|
||||
- FortiClient EMS admin type.
|
||||
type: str
|
||||
choices:
|
||||
- Windows
|
||||
- LDAP
|
||||
admin_username:
|
||||
description:
|
||||
- FortiClient EMS admin username.
|
||||
type: str
|
||||
https_port:
|
||||
description:
|
||||
- "FortiClient EMS HTTPS access port number. (1 - 65535)."
|
||||
type: int
|
||||
listen_port:
|
||||
description:
|
||||
- "FortiClient EMS telemetry listen port number. (1 - 65535)."
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- FortiClient Enterprise Management Server (EMS) name.
|
||||
required: true
|
||||
type: str
|
||||
rest_api_auth:
|
||||
description:
|
||||
- FortiClient EMS REST API authentication.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- userpass
|
||||
serial_number:
|
||||
description:
|
||||
- FortiClient EMS Serial Number.
|
||||
type: str
|
||||
upload_port:
|
||||
description:
|
||||
- "FortiClient EMS telemetry upload port number. (1 - 65535)."
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure FortiClient Enterprise Management Server (EMS) entries.
|
||||
fortios_endpoint_control_forticlient_ems:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
endpoint_control_forticlient_ems:
|
||||
address: "<your_own_value> (source firewall.address.name)"
|
||||
admin_password: "<your_own_value>"
|
||||
admin_type: "Windows"
|
||||
admin_username: "<your_own_value>"
|
||||
https_port: "7"
|
||||
listen_port: "8"
|
||||
name: "default_name_9"
|
||||
rest_api_auth: "disable"
|
||||
serial_number: "<your_own_value>"
|
||||
upload_port: "12"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_endpoint_control_forticlient_ems_data(json):
|
||||
option_list = ['address', 'admin_password', 'admin_type',
|
||||
'admin_username', 'https_port', 'listen_port',
|
||||
'name', 'rest_api_auth', 'serial_number',
|
||||
'upload_port']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def endpoint_control_forticlient_ems(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['endpoint_control_forticlient_ems'] and data['endpoint_control_forticlient_ems']:
|
||||
state = data['endpoint_control_forticlient_ems']['state']
|
||||
else:
|
||||
state = True
|
||||
endpoint_control_forticlient_ems_data = data['endpoint_control_forticlient_ems']
|
||||
filtered_data = underscore_to_hyphen(filter_endpoint_control_forticlient_ems_data(endpoint_control_forticlient_ems_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('endpoint-control',
|
||||
'forticlient-ems',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('endpoint-control',
|
||||
'forticlient-ems',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_endpoint_control(data, fos):
|
||||
|
||||
if data['endpoint_control_forticlient_ems']:
|
||||
resp = endpoint_control_forticlient_ems(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"endpoint_control_forticlient_ems": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"address": {"required": False, "type": "str"},
|
||||
"admin_password": {"required": False, "type": "str"},
|
||||
"admin_type": {"required": False, "type": "str",
|
||||
"choices": ["Windows", "LDAP"]},
|
||||
"admin_username": {"required": False, "type": "str"},
|
||||
"https_port": {"required": False, "type": "int"},
|
||||
"listen_port": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"rest_api_auth": {"required": False, "type": "str",
|
||||
"choices": ["disable", "userpass"]},
|
||||
"serial_number": {"required": False, "type": "str"},
|
||||
"upload_port": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,336 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_endpoint_control_forticlient_registration_sync
|
||||
short_description: Configure FortiClient registration synchronization settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify endpoint_control feature and forticlient_registration_sync category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
endpoint_control_forticlient_registration_sync:
|
||||
description:
|
||||
- Configure FortiClient registration synchronization settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
peer_ip:
|
||||
description:
|
||||
- IP address of the peer FortiGate for endpoint license synchronization.
|
||||
type: str
|
||||
peer_name:
|
||||
description:
|
||||
- Peer name.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure FortiClient registration synchronization settings.
|
||||
fortios_endpoint_control_forticlient_registration_sync:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
endpoint_control_forticlient_registration_sync:
|
||||
peer_ip: "<your_own_value>"
|
||||
peer_name: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_endpoint_control_forticlient_registration_sync_data(json):
|
||||
option_list = ['peer_ip', 'peer_name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def endpoint_control_forticlient_registration_sync(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['endpoint_control_forticlient_registration_sync'] and data['endpoint_control_forticlient_registration_sync']:
|
||||
state = data['endpoint_control_forticlient_registration_sync']['state']
|
||||
else:
|
||||
state = True
|
||||
endpoint_control_forticlient_registration_sync_data = data['endpoint_control_forticlient_registration_sync']
|
||||
filtered_data = underscore_to_hyphen(filter_endpoint_control_forticlient_registration_sync_data(endpoint_control_forticlient_registration_sync_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('endpoint-control',
|
||||
'forticlient-registration-sync',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('endpoint-control',
|
||||
'forticlient-registration-sync',
|
||||
mkey=filtered_data['peer-name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_endpoint_control(data, fos):
|
||||
|
||||
if data['endpoint_control_forticlient_registration_sync']:
|
||||
resp = endpoint_control_forticlient_registration_sync(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"endpoint_control_forticlient_registration_sync": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"peer_ip": {"required": False, "type": "str"},
|
||||
"peer_name": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,392 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_endpoint_control_settings
|
||||
short_description: Configure endpoint control settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify endpoint_control feature and settings category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
endpoint_control_settings:
|
||||
description:
|
||||
- Configure endpoint control settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
download_custom_link:
|
||||
description:
|
||||
- Customized URL for downloading FortiClient.
|
||||
type: str
|
||||
download_location:
|
||||
description:
|
||||
- FortiClient download location (FortiGuard or custom).
|
||||
type: str
|
||||
choices:
|
||||
- fortiguard
|
||||
- custom
|
||||
forticlient_avdb_update_interval:
|
||||
description:
|
||||
- Period of time between FortiClient AntiVirus database updates (0 - 24 hours).
|
||||
type: int
|
||||
forticlient_dereg_unsupported_client:
|
||||
description:
|
||||
- Enable/disable deregistering unsupported FortiClient endpoints.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
forticlient_ems_rest_api_call_timeout:
|
||||
description:
|
||||
- FortiClient EMS call timeout in milliseconds (500 - 30000 milliseconds).
|
||||
type: int
|
||||
forticlient_keepalive_interval:
|
||||
description:
|
||||
- Interval between two KeepAlive messages from FortiClient (20 - 300 sec).
|
||||
type: int
|
||||
forticlient_offline_grace:
|
||||
description:
|
||||
- Enable/disable grace period for offline registered clients.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
forticlient_offline_grace_interval:
|
||||
description:
|
||||
- Grace period for offline registered FortiClient (60 - 600 sec).
|
||||
type: int
|
||||
forticlient_reg_key:
|
||||
description:
|
||||
- FortiClient registration key.
|
||||
type: str
|
||||
forticlient_reg_key_enforce:
|
||||
description:
|
||||
- Enable/disable requiring or enforcing FortiClient registration keys.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
forticlient_reg_timeout:
|
||||
description:
|
||||
- FortiClient registration license timeout (days, min = 1, max = 180, 0 means unlimited).
|
||||
type: int
|
||||
forticlient_sys_update_interval:
|
||||
description:
|
||||
- Interval between two system update messages from FortiClient (30 - 1440 min).
|
||||
type: int
|
||||
forticlient_user_avatar:
|
||||
description:
|
||||
- Enable/disable uploading FortiClient user avatars.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
forticlient_warning_interval:
|
||||
description:
|
||||
- Period of time between FortiClient portal warnings (0 - 24 hours).
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure endpoint control settings.
|
||||
fortios_endpoint_control_settings:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
endpoint_control_settings:
|
||||
download_custom_link: "<your_own_value>"
|
||||
download_location: "fortiguard"
|
||||
forticlient_avdb_update_interval: "5"
|
||||
forticlient_dereg_unsupported_client: "enable"
|
||||
forticlient_ems_rest_api_call_timeout: "7"
|
||||
forticlient_keepalive_interval: "8"
|
||||
forticlient_offline_grace: "enable"
|
||||
forticlient_offline_grace_interval: "10"
|
||||
forticlient_reg_key: "<your_own_value>"
|
||||
forticlient_reg_key_enforce: "enable"
|
||||
forticlient_reg_timeout: "13"
|
||||
forticlient_sys_update_interval: "14"
|
||||
forticlient_user_avatar: "enable"
|
||||
forticlient_warning_interval: "16"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_endpoint_control_settings_data(json):
|
||||
option_list = ['download_custom_link', 'download_location', 'forticlient_avdb_update_interval',
|
||||
'forticlient_dereg_unsupported_client', 'forticlient_ems_rest_api_call_timeout', 'forticlient_keepalive_interval',
|
||||
'forticlient_offline_grace', 'forticlient_offline_grace_interval', 'forticlient_reg_key',
|
||||
'forticlient_reg_key_enforce', 'forticlient_reg_timeout', 'forticlient_sys_update_interval',
|
||||
'forticlient_user_avatar', 'forticlient_warning_interval']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def endpoint_control_settings(data, fos):
|
||||
vdom = data['vdom']
|
||||
endpoint_control_settings_data = data['endpoint_control_settings']
|
||||
filtered_data = underscore_to_hyphen(filter_endpoint_control_settings_data(endpoint_control_settings_data))
|
||||
|
||||
return fos.set('endpoint-control',
|
||||
'settings',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_endpoint_control(data, fos):
|
||||
|
||||
if data['endpoint_control_settings']:
|
||||
resp = endpoint_control_settings(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"endpoint_control_settings": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"download_custom_link": {"required": False, "type": "str"},
|
||||
"download_location": {"required": False, "type": "str",
|
||||
"choices": ["fortiguard", "custom"]},
|
||||
"forticlient_avdb_update_interval": {"required": False, "type": "int"},
|
||||
"forticlient_dereg_unsupported_client": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"forticlient_ems_rest_api_call_timeout": {"required": False, "type": "int"},
|
||||
"forticlient_keepalive_interval": {"required": False, "type": "int"},
|
||||
"forticlient_offline_grace": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"forticlient_offline_grace_interval": {"required": False, "type": "int"},
|
||||
"forticlient_reg_key": {"required": False, "type": "str"},
|
||||
"forticlient_reg_key_enforce": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"forticlient_reg_timeout": {"required": False, "type": "int"},
|
||||
"forticlient_sys_update_interval": {"required": False, "type": "int"},
|
||||
"forticlient_user_avatar": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"forticlient_warning_interval": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_endpoint_control(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,627 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_extender_controller_extender
|
||||
short_description: Extender controller configuration in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify extender_controller feature and extender category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
extender_controller_extender:
|
||||
description:
|
||||
- Extender controller configuration.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
aaa_shared_secret:
|
||||
description:
|
||||
- AAA shared secret.
|
||||
type: str
|
||||
access_point_name:
|
||||
description:
|
||||
- Access point name(APN).
|
||||
type: str
|
||||
admin:
|
||||
description:
|
||||
- FortiExtender Administration (enable or disable).
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- discovered
|
||||
- enable
|
||||
at_dial_script:
|
||||
description:
|
||||
- Initialization AT commands specific to the MODEM.
|
||||
type: str
|
||||
billing_start_day:
|
||||
description:
|
||||
- Billing start day.
|
||||
type: int
|
||||
cdma_aaa_spi:
|
||||
description:
|
||||
- CDMA AAA SPI.
|
||||
type: str
|
||||
cdma_ha_spi:
|
||||
description:
|
||||
- CDMA HA SPI.
|
||||
type: str
|
||||
cdma_nai:
|
||||
description:
|
||||
- NAI for CDMA MODEMS.
|
||||
type: str
|
||||
conn_status:
|
||||
description:
|
||||
- Connection status.
|
||||
type: int
|
||||
description:
|
||||
description:
|
||||
- Description.
|
||||
type: str
|
||||
dial_mode:
|
||||
description:
|
||||
- Dial mode (dial-on-demand or always-connect).
|
||||
type: str
|
||||
choices:
|
||||
- dial-on-demand
|
||||
- always-connect
|
||||
dial_status:
|
||||
description:
|
||||
- Dial status.
|
||||
type: int
|
||||
ext_name:
|
||||
description:
|
||||
- FortiExtender name.
|
||||
type: str
|
||||
ha_shared_secret:
|
||||
description:
|
||||
- HA shared secret.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- FortiExtender serial number.
|
||||
required: true
|
||||
type: str
|
||||
ifname:
|
||||
description:
|
||||
- FortiExtender interface name.
|
||||
type: str
|
||||
initiated_update:
|
||||
description:
|
||||
- Allow/disallow network initiated updates to the MODEM.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
mode:
|
||||
description:
|
||||
- FortiExtender mode.
|
||||
type: str
|
||||
choices:
|
||||
- standalone
|
||||
- redundant
|
||||
modem_passwd:
|
||||
description:
|
||||
- MODEM password.
|
||||
type: str
|
||||
modem_type:
|
||||
description:
|
||||
- MODEM type (CDMA, GSM/LTE or WIMAX).
|
||||
type: str
|
||||
choices:
|
||||
- cdma
|
||||
- gsm/lte
|
||||
- wimax
|
||||
multi_mode:
|
||||
description:
|
||||
- MODEM mode of operation(3G,LTE,etc).
|
||||
type: str
|
||||
choices:
|
||||
- auto
|
||||
- auto-3g
|
||||
- force-lte
|
||||
- force-3g
|
||||
- force-2g
|
||||
ppp_auth_protocol:
|
||||
description:
|
||||
- PPP authentication protocol (PAP,CHAP or auto).
|
||||
type: str
|
||||
choices:
|
||||
- auto
|
||||
- pap
|
||||
- chap
|
||||
ppp_echo_request:
|
||||
description:
|
||||
- Enable/disable PPP echo request.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ppp_password:
|
||||
description:
|
||||
- PPP password.
|
||||
type: str
|
||||
ppp_username:
|
||||
description:
|
||||
- PPP username.
|
||||
type: str
|
||||
primary_ha:
|
||||
description:
|
||||
- Primary HA.
|
||||
type: str
|
||||
quota_limit_mb:
|
||||
description:
|
||||
- Monthly quota limit (MB).
|
||||
type: int
|
||||
redial:
|
||||
description:
|
||||
- Number of redials allowed based on failed attempts.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
- 8
|
||||
- 9
|
||||
- 10
|
||||
redundant_intf:
|
||||
description:
|
||||
- Redundant interface.
|
||||
type: str
|
||||
roaming:
|
||||
description:
|
||||
- Enable/disable MODEM roaming.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
role:
|
||||
description:
|
||||
- FortiExtender work role(Primary, Secondary, None).
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- primary
|
||||
- secondary
|
||||
secondary_ha:
|
||||
description:
|
||||
- Secondary HA.
|
||||
type: str
|
||||
sim_pin:
|
||||
description:
|
||||
- SIM PIN.
|
||||
type: str
|
||||
vdom:
|
||||
description:
|
||||
- VDOM
|
||||
type: int
|
||||
wimax_auth_protocol:
|
||||
description:
|
||||
- WiMax authentication protocol(TLS or TTLS).
|
||||
type: str
|
||||
choices:
|
||||
- tls
|
||||
- ttls
|
||||
wimax_carrier:
|
||||
description:
|
||||
- WiMax carrier.
|
||||
type: str
|
||||
wimax_realm:
|
||||
description:
|
||||
- WiMax realm.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Extender controller configuration.
|
||||
fortios_extender_controller_extender:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
extender_controller_extender:
|
||||
aaa_shared_secret: "<your_own_value>"
|
||||
access_point_name: "<your_own_value>"
|
||||
admin: "disable"
|
||||
at_dial_script: "<your_own_value>"
|
||||
billing_start_day: "7"
|
||||
cdma_aaa_spi: "<your_own_value>"
|
||||
cdma_ha_spi: "<your_own_value>"
|
||||
cdma_nai: "<your_own_value>"
|
||||
conn_status: "11"
|
||||
description: "<your_own_value>"
|
||||
dial_mode: "dial-on-demand"
|
||||
dial_status: "14"
|
||||
ext_name: "<your_own_value>"
|
||||
ha_shared_secret: "<your_own_value>"
|
||||
id: "17"
|
||||
ifname: "<your_own_value>"
|
||||
initiated_update: "enable"
|
||||
mode: "standalone"
|
||||
modem_passwd: "<your_own_value>"
|
||||
modem_type: "cdma"
|
||||
multi_mode: "auto"
|
||||
ppp_auth_protocol: "auto"
|
||||
ppp_echo_request: "enable"
|
||||
ppp_password: "<your_own_value>"
|
||||
ppp_username: "<your_own_value>"
|
||||
primary_ha: "<your_own_value>"
|
||||
quota_limit_mb: "29"
|
||||
redial: "none"
|
||||
redundant_intf: "<your_own_value>"
|
||||
roaming: "enable"
|
||||
role: "none"
|
||||
secondary_ha: "<your_own_value>"
|
||||
sim_pin: "<your_own_value>"
|
||||
vdom: "36"
|
||||
wimax_auth_protocol: "tls"
|
||||
wimax_carrier: "<your_own_value>"
|
||||
wimax_realm: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_extender_controller_extender_data(json):
|
||||
option_list = ['aaa_shared_secret', 'access_point_name', 'admin',
|
||||
'at_dial_script', 'billing_start_day', 'cdma_aaa_spi',
|
||||
'cdma_ha_spi', 'cdma_nai', 'conn_status',
|
||||
'description', 'dial_mode', 'dial_status',
|
||||
'ext_name', 'ha_shared_secret', 'id',
|
||||
'ifname', 'initiated_update', 'mode',
|
||||
'modem_passwd', 'modem_type', 'multi_mode',
|
||||
'ppp_auth_protocol', 'ppp_echo_request', 'ppp_password',
|
||||
'ppp_username', 'primary_ha', 'quota_limit_mb',
|
||||
'redial', 'redundant_intf', 'roaming',
|
||||
'role', 'secondary_ha', 'sim_pin',
|
||||
'vdom', 'wimax_auth_protocol', 'wimax_carrier',
|
||||
'wimax_realm']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def extender_controller_extender(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['extender_controller_extender'] and data['extender_controller_extender']:
|
||||
state = data['extender_controller_extender']['state']
|
||||
else:
|
||||
state = True
|
||||
extender_controller_extender_data = data['extender_controller_extender']
|
||||
filtered_data = underscore_to_hyphen(filter_extender_controller_extender_data(extender_controller_extender_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('extender-controller',
|
||||
'extender',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('extender-controller',
|
||||
'extender',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_extender_controller(data, fos):
|
||||
|
||||
if data['extender_controller_extender']:
|
||||
resp = extender_controller_extender(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"extender_controller_extender": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"aaa_shared_secret": {"required": False, "type": "str"},
|
||||
"access_point_name": {"required": False, "type": "str"},
|
||||
"admin": {"required": False, "type": "str",
|
||||
"choices": ["disable", "discovered", "enable"]},
|
||||
"at_dial_script": {"required": False, "type": "str"},
|
||||
"billing_start_day": {"required": False, "type": "int"},
|
||||
"cdma_aaa_spi": {"required": False, "type": "str"},
|
||||
"cdma_ha_spi": {"required": False, "type": "str"},
|
||||
"cdma_nai": {"required": False, "type": "str"},
|
||||
"conn_status": {"required": False, "type": "int"},
|
||||
"description": {"required": False, "type": "str"},
|
||||
"dial_mode": {"required": False, "type": "str",
|
||||
"choices": ["dial-on-demand", "always-connect"]},
|
||||
"dial_status": {"required": False, "type": "int"},
|
||||
"ext_name": {"required": False, "type": "str"},
|
||||
"ha_shared_secret": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "str"},
|
||||
"ifname": {"required": False, "type": "str"},
|
||||
"initiated_update": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"mode": {"required": False, "type": "str",
|
||||
"choices": ["standalone", "redundant"]},
|
||||
"modem_passwd": {"required": False, "type": "str"},
|
||||
"modem_type": {"required": False, "type": "str",
|
||||
"choices": ["cdma", "gsm/lte", "wimax"]},
|
||||
"multi_mode": {"required": False, "type": "str",
|
||||
"choices": ["auto", "auto-3g", "force-lte",
|
||||
"force-3g", "force-2g"]},
|
||||
"ppp_auth_protocol": {"required": False, "type": "str",
|
||||
"choices": ["auto", "pap", "chap"]},
|
||||
"ppp_echo_request": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ppp_password": {"required": False, "type": "str"},
|
||||
"ppp_username": {"required": False, "type": "str"},
|
||||
"primary_ha": {"required": False, "type": "str"},
|
||||
"quota_limit_mb": {"required": False, "type": "int"},
|
||||
"redial": {"required": False, "type": "str",
|
||||
"choices": ["none", "1", "2",
|
||||
"3", "4", "5",
|
||||
"6", "7", "8",
|
||||
"9", "10"]},
|
||||
"redundant_intf": {"required": False, "type": "str"},
|
||||
"roaming": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"role": {"required": False, "type": "str",
|
||||
"choices": ["none", "primary", "secondary"]},
|
||||
"secondary_ha": {"required": False, "type": "str"},
|
||||
"sim_pin": {"required": False, "type": "str"},
|
||||
"vdom": {"required": False, "type": "int"},
|
||||
"wimax_auth_protocol": {"required": False, "type": "str",
|
||||
"choices": ["tls", "ttls"]},
|
||||
"wimax_carrier": {"required": False, "type": "str"},
|
||||
"wimax_realm": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_extender_controller(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_extender_controller(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,282 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_facts
|
||||
version_added: "2.9"
|
||||
short_description: Get facts about fortios devices.
|
||||
description:
|
||||
- Collects facts from network devices running the fortios operating
|
||||
system. This module places the facts gathered in the fact tree keyed by the
|
||||
respective resource name. This facts module will only collect those
|
||||
facts which user specified in playbook.
|
||||
author:
|
||||
- Don Yao (@fortinetps)
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Support both legacy mode (local_action) and httpapi
|
||||
- Legacy mode run as a local_action in your playbook, requires fortiosapi library developed by Fortinet
|
||||
- httpapi mode is the new recommend way for network modules
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
required: false
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
required: false
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
required: false
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: false
|
||||
required: false
|
||||
gather_subset:
|
||||
description:
|
||||
- When supplied, this argument will restrict the facts collected
|
||||
to a given subset. Possible values for this argument include
|
||||
system_current-admins_select, system_firmware_select,
|
||||
system_fortimanager_status, system_ha-checksums_select,
|
||||
system_interface_select, system_status_select and system_time_select
|
||||
type: list
|
||||
elements: dict
|
||||
required: true
|
||||
suboptions:
|
||||
fact:
|
||||
description:
|
||||
- Name of the facts to gather
|
||||
type: str
|
||||
required: true
|
||||
filters:
|
||||
description:
|
||||
- Filters apply when gathering facts
|
||||
type: list
|
||||
elements: dict
|
||||
required: false
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
|
||||
tasks:
|
||||
- name: gather basic system status facts
|
||||
fortios_facts:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
gather_subset:
|
||||
- fact: 'system_status_select'
|
||||
|
||||
- name: gather all physical interfaces status facts
|
||||
fortios_facts:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
gather_subset:
|
||||
- fact: 'system_interface_select'
|
||||
|
||||
- name: gather gather all physical and vlan interfaces status facts
|
||||
fortios_facts:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
gather_subset:
|
||||
- fact: 'system_interface_select'
|
||||
filters:
|
||||
- include_vlan: true
|
||||
|
||||
- name: gather basic system info and physical interface port3 status facts
|
||||
fortios_facts:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
gather_subset:
|
||||
- fact: 'system_status_select'
|
||||
- fact: 'system_interface_select'
|
||||
filters:
|
||||
- interface_name: 'port3'
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'GET'
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "firmware"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "system"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
ansible_facts:
|
||||
description: The list of fact subsets collected from the device
|
||||
returned: always
|
||||
type: dict
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
from ansible.module_utils.network.fortios.argspec.facts.facts import FactsArgs
|
||||
from ansible.module_utils.network.fortios.facts.facts import Facts
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def main():
|
||||
""" Main entry point for AnsibleModule
|
||||
"""
|
||||
argument_spec = FactsArgs.argument_spec
|
||||
|
||||
module = AnsibleModule(argument_spec=argument_spec,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
warnings = []
|
||||
connection = Connection(module._socket_path)
|
||||
module._connection = connection
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
result = Facts(module, fos).get_facts()
|
||||
|
||||
ansible_facts, additional_warnings = result
|
||||
warnings.extend(additional_warnings)
|
||||
|
||||
module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
warnings = []
|
||||
|
||||
fos = FortiOSAPI()
|
||||
login(module.params, fos)
|
||||
module._connection = fos
|
||||
|
||||
result = Facts(module, fos).get_facts()
|
||||
|
||||
ansible_facts, additional_warnings = result
|
||||
warnings.extend(additional_warnings)
|
||||
|
||||
module.exit_json(ansible_facts=ansible_facts, warnings=warnings)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,492 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_DoS_policy
|
||||
short_description: Configure IPv4 DoS policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and DoS_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_DoS_policy:
|
||||
description:
|
||||
- Configure IPv4 DoS policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
anomaly:
|
||||
description:
|
||||
- Anomaly name.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Action taken when the threshold is reached.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
log:
|
||||
description:
|
||||
- Enable/disable anomaly logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Anomaly name.
|
||||
required: true
|
||||
type: str
|
||||
quarantine:
|
||||
description:
|
||||
- Quarantine method.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- attacker
|
||||
quarantine_expiry:
|
||||
description:
|
||||
- Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m). Requires quarantine set to attacker.
|
||||
type: str
|
||||
quarantine_log:
|
||||
description:
|
||||
- Enable/disable quarantine logging.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this anomaly.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
threshold:
|
||||
description:
|
||||
- Anomaly threshold. Number of detected instances per minute that triggers the anomaly action.
|
||||
type: int
|
||||
threshold(default):
|
||||
description:
|
||||
- Number of detected instances per minute which triggers action (1 - 2147483647). Note that each anomaly has a different threshold
|
||||
value assigned to it.
|
||||
type: int
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address name from available addresses.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
interface:
|
||||
description:
|
||||
- Incoming interface name from available interfaces. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
service:
|
||||
description:
|
||||
- Service object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address name from available addresses.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv4 DoS policies.
|
||||
fortios_firewall_DoS_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_DoS_policy:
|
||||
anomaly:
|
||||
-
|
||||
action: "pass"
|
||||
log: "enable"
|
||||
name: "default_name_6"
|
||||
quarantine: "none"
|
||||
quarantine_expiry: "<your_own_value>"
|
||||
quarantine_log: "disable"
|
||||
status: "disable"
|
||||
threshold: "11"
|
||||
threshold(default): "12"
|
||||
comments: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_15 (source firewall.address.name firewall.addrgrp.name)"
|
||||
interface: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
policyid: "17"
|
||||
service:
|
||||
-
|
||||
name: "default_name_19 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_21 (source firewall.address.name firewall.addrgrp.name)"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_DoS_policy_data(json):
|
||||
option_list = ['anomaly', 'comments', 'dstaddr',
|
||||
'interface', 'policyid', 'service',
|
||||
'srcaddr', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_DoS_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_DoS_policy'] and data['firewall_DoS_policy']:
|
||||
state = data['firewall_DoS_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_DoS_policy_data = data['firewall_DoS_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_DoS_policy_data(firewall_DoS_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'DoS-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'DoS-policy',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_DoS_policy']:
|
||||
resp = firewall_DoS_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_DoS_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"anomaly": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block"]},
|
||||
"log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"quarantine": {"required": False, "type": "str",
|
||||
"choices": ["none", "attacker"]},
|
||||
"quarantine_expiry": {"required": False, "type": "str"},
|
||||
"quarantine_log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"threshold": {"required": False, "type": "int"},
|
||||
"threshold(default)": {"required": False, "type": "int"}
|
||||
}},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"interface": {"required": False, "type": "str"},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,492 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_DoS_policy6
|
||||
short_description: Configure IPv6 DoS policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and DoS_policy6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_DoS_policy6:
|
||||
description:
|
||||
- Configure IPv6 DoS policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
anomaly:
|
||||
description:
|
||||
- Anomaly name.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Action taken when the threshold is reached.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
log:
|
||||
description:
|
||||
- Enable/disable anomaly logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Anomaly name.
|
||||
required: true
|
||||
type: str
|
||||
quarantine:
|
||||
description:
|
||||
- Quarantine method.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- attacker
|
||||
quarantine_expiry:
|
||||
description:
|
||||
- Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m). Requires quarantine set to attacker.
|
||||
type: str
|
||||
quarantine_log:
|
||||
description:
|
||||
- Enable/disable quarantine logging.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this anomaly.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
threshold:
|
||||
description:
|
||||
- Anomaly threshold. Number of detected instances per minute that triggers the anomaly action.
|
||||
type: int
|
||||
threshold(default):
|
||||
description:
|
||||
- Number of detected instances per minute which triggers action (1 - 2147483647). Note that each anomaly has a different threshold
|
||||
value assigned to it.
|
||||
type: int
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address name from available addresses.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
interface:
|
||||
description:
|
||||
- Incoming interface name from available interfaces. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
service:
|
||||
description:
|
||||
- Service object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address name from available addresses.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 DoS policies.
|
||||
fortios_firewall_DoS_policy6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_DoS_policy6:
|
||||
anomaly:
|
||||
-
|
||||
action: "pass"
|
||||
log: "enable"
|
||||
name: "default_name_6"
|
||||
quarantine: "none"
|
||||
quarantine_expiry: "<your_own_value>"
|
||||
quarantine_log: "disable"
|
||||
status: "disable"
|
||||
threshold: "11"
|
||||
threshold(default): "12"
|
||||
comments: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_15 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
interface: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
policyid: "17"
|
||||
service:
|
||||
-
|
||||
name: "default_name_19 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_21 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_DoS_policy6_data(json):
|
||||
option_list = ['anomaly', 'comments', 'dstaddr',
|
||||
'interface', 'policyid', 'service',
|
||||
'srcaddr', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_DoS_policy6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_DoS_policy6'] and data['firewall_DoS_policy6']:
|
||||
state = data['firewall_DoS_policy6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_DoS_policy6_data = data['firewall_DoS_policy6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_DoS_policy6_data(firewall_DoS_policy6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'DoS-policy6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'DoS-policy6',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_DoS_policy6']:
|
||||
resp = firewall_DoS_policy6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_DoS_policy6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"anomaly": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block"]},
|
||||
"log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"quarantine": {"required": False, "type": "str",
|
||||
"choices": ["none", "attacker"]},
|
||||
"quarantine_expiry": {"required": False, "type": "str"},
|
||||
"quarantine_log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"threshold": {"required": False, "type": "int"},
|
||||
"threshold(default)": {"required": False, "type": "int"}
|
||||
}},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"interface": {"required": False, "type": "str"},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,571 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_address
|
||||
short_description: Configure IPv4 addresses in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and address category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_address:
|
||||
description:
|
||||
- Configure IPv4 addresses.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
allow_routing:
|
||||
description:
|
||||
- Enable/disable use of this address in the static route configuration.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
associated_interface:
|
||||
description:
|
||||
- Network interface associated with address. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
cache_ttl:
|
||||
description:
|
||||
- Defines the minimal TTL of individual IP addresses in FQDN cache measured in seconds.
|
||||
type: int
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
country:
|
||||
description:
|
||||
- IP addresses associated to a specific country.
|
||||
type: str
|
||||
end_ip:
|
||||
description:
|
||||
- Final IP address (inclusive) in the range for the address.
|
||||
type: str
|
||||
epg_name:
|
||||
description:
|
||||
- Endpoint group name.
|
||||
type: str
|
||||
filter:
|
||||
description:
|
||||
- Match criteria filter.
|
||||
type: str
|
||||
fqdn:
|
||||
description:
|
||||
- Fully Qualified Domain Name address.
|
||||
type: str
|
||||
list:
|
||||
description:
|
||||
- IP address list.
|
||||
type: list
|
||||
suboptions:
|
||||
ip:
|
||||
description:
|
||||
- IP.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Address name.
|
||||
required: true
|
||||
type: str
|
||||
obj_id:
|
||||
description:
|
||||
- Object ID for NSX.
|
||||
type: str
|
||||
organization:
|
||||
description:
|
||||
- "Organization domain name (Syntax: organization/domain)."
|
||||
type: str
|
||||
policy_group:
|
||||
description:
|
||||
- Policy group name.
|
||||
type: str
|
||||
sdn:
|
||||
description:
|
||||
- SDN.
|
||||
type: str
|
||||
choices:
|
||||
- aci
|
||||
- aws
|
||||
- azure
|
||||
- gcp
|
||||
- nsx
|
||||
- nuage
|
||||
- oci
|
||||
- openstack
|
||||
sdn_tag:
|
||||
description:
|
||||
- SDN Tag.
|
||||
type: str
|
||||
start_ip:
|
||||
description:
|
||||
- First IP address (inclusive) in the range for the address.
|
||||
type: str
|
||||
subnet:
|
||||
description:
|
||||
- IP address and subnet mask of address.
|
||||
type: str
|
||||
subnet_name:
|
||||
description:
|
||||
- Subnet name.
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
tenant:
|
||||
description:
|
||||
- Tenant.
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Type of address.
|
||||
type: str
|
||||
choices:
|
||||
- ipmask
|
||||
- iprange
|
||||
- fqdn
|
||||
- geography
|
||||
- wildcard
|
||||
- wildcard-fqdn
|
||||
- dynamic
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable address visibility in the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
wildcard:
|
||||
description:
|
||||
- IP address and wildcard netmask.
|
||||
type: str
|
||||
wildcard_fqdn:
|
||||
description:
|
||||
- Fully Qualified Domain Name with wildcard characters.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv4 addresses.
|
||||
fortios_firewall_address:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_address:
|
||||
allow_routing: "enable"
|
||||
associated_interface: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
cache_ttl: "5"
|
||||
color: "6"
|
||||
comment: "Comment."
|
||||
country: "<your_own_value>"
|
||||
end_ip: "<your_own_value>"
|
||||
epg_name: "<your_own_value>"
|
||||
filter: "<your_own_value>"
|
||||
fqdn: "<your_own_value>"
|
||||
list:
|
||||
-
|
||||
ip: "<your_own_value>"
|
||||
name: "default_name_15"
|
||||
obj_id: "<your_own_value>"
|
||||
organization: "<your_own_value>"
|
||||
policy_group: "<your_own_value>"
|
||||
sdn: "aci"
|
||||
sdn_tag: "<your_own_value>"
|
||||
start_ip: "<your_own_value>"
|
||||
subnet: "<your_own_value>"
|
||||
subnet_name: "<your_own_value>"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_26"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_28 (source system.object-tagging.tags.name)"
|
||||
tenant: "<your_own_value>"
|
||||
type: "ipmask"
|
||||
uuid: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
wildcard: "<your_own_value>"
|
||||
wildcard_fqdn: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_address_data(json):
|
||||
option_list = ['allow_routing', 'associated_interface', 'cache_ttl',
|
||||
'color', 'comment', 'country',
|
||||
'end_ip', 'epg_name', 'filter',
|
||||
'fqdn', 'list', 'name',
|
||||
'obj_id', 'organization', 'policy_group',
|
||||
'sdn', 'sdn_tag', 'start_ip',
|
||||
'subnet', 'subnet_name', 'tagging',
|
||||
'tenant', 'type', 'uuid',
|
||||
'visibility', 'wildcard', 'wildcard_fqdn']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_address(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_address'] and data['firewall_address']:
|
||||
state = data['firewall_address']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_address_data = data['firewall_address']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_address_data(firewall_address_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'address',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'address',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_address']:
|
||||
resp = firewall_address(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_address": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"allow_routing": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"associated_interface": {"required": False, "type": "str"},
|
||||
"cache_ttl": {"required": False, "type": "int"},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"country": {"required": False, "type": "str"},
|
||||
"end_ip": {"required": False, "type": "str"},
|
||||
"epg_name": {"required": False, "type": "str"},
|
||||
"filter": {"required": False, "type": "str"},
|
||||
"fqdn": {"required": False, "type": "str"},
|
||||
"list": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"ip": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"obj_id": {"required": False, "type": "str"},
|
||||
"organization": {"required": False, "type": "str"},
|
||||
"policy_group": {"required": False, "type": "str"},
|
||||
"sdn": {"required": False, "type": "str",
|
||||
"choices": ["aci", "aws", "azure",
|
||||
"gcp", "nsx", "nuage",
|
||||
"oci", "openstack"]},
|
||||
"sdn_tag": {"required": False, "type": "str"},
|
||||
"start_ip": {"required": False, "type": "str"},
|
||||
"subnet": {"required": False, "type": "str"},
|
||||
"subnet_name": {"required": False, "type": "str"},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"tenant": {"required": False, "type": "str"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["ipmask", "iprange", "fqdn",
|
||||
"geography", "wildcard", "wildcard-fqdn",
|
||||
"dynamic"]},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"wildcard": {"required": False, "type": "str"},
|
||||
"wildcard_fqdn": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,536 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_address6
|
||||
short_description: Configure IPv6 firewall addresses in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and address6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_address6:
|
||||
description:
|
||||
- Configure IPv6 firewall addresses.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
cache_ttl:
|
||||
description:
|
||||
- Minimal TTL of individual IPv6 addresses in FQDN cache.
|
||||
type: int
|
||||
color:
|
||||
description:
|
||||
- Integer value to determine the color of the icon in the GUI (range 1 to 32).
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
end_ip:
|
||||
description:
|
||||
- "Final IP address (inclusive) in the range for the address (format: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx)."
|
||||
type: str
|
||||
fqdn:
|
||||
description:
|
||||
- Fully qualified domain name.
|
||||
type: str
|
||||
host:
|
||||
description:
|
||||
- Host Address.
|
||||
type: str
|
||||
host_type:
|
||||
description:
|
||||
- Host type.
|
||||
type: str
|
||||
choices:
|
||||
- any
|
||||
- specific
|
||||
ip6:
|
||||
description:
|
||||
- "IPv6 address prefix (format: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xxx)."
|
||||
type: str
|
||||
list:
|
||||
description:
|
||||
- IP address list.
|
||||
type: list
|
||||
suboptions:
|
||||
ip:
|
||||
description:
|
||||
- IP.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Address name.
|
||||
required: true
|
||||
type: str
|
||||
obj_id:
|
||||
description:
|
||||
- Object ID for NSX.
|
||||
type: str
|
||||
sdn:
|
||||
description:
|
||||
- SDN.
|
||||
type: str
|
||||
choices:
|
||||
- nsx
|
||||
start_ip:
|
||||
description:
|
||||
- "First IP address (inclusive) in the range for the address (format: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx)."
|
||||
type: str
|
||||
subnet_segment:
|
||||
description:
|
||||
- IPv6 subnet segments.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Name.
|
||||
required: true
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Subnet segment type.
|
||||
type: str
|
||||
choices:
|
||||
- any
|
||||
- specific
|
||||
value:
|
||||
description:
|
||||
- Subnet segment value.
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
template:
|
||||
description:
|
||||
- IPv6 address template. Source firewall.address6-template.name.
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Type of IPv6 address object .
|
||||
type: str
|
||||
choices:
|
||||
- ipprefix
|
||||
- iprange
|
||||
- fqdn
|
||||
- dynamic
|
||||
- template
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable the visibility of the object in the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 firewall addresses.
|
||||
fortios_firewall_address6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_address6:
|
||||
cache_ttl: "3"
|
||||
color: "4"
|
||||
comment: "Comment."
|
||||
end_ip: "<your_own_value>"
|
||||
fqdn: "<your_own_value>"
|
||||
host: "<your_own_value>"
|
||||
host_type: "any"
|
||||
ip6: "<your_own_value>"
|
||||
list:
|
||||
-
|
||||
ip: "<your_own_value>"
|
||||
name: "default_name_13"
|
||||
obj_id: "<your_own_value>"
|
||||
sdn: "nsx"
|
||||
start_ip: "<your_own_value>"
|
||||
subnet_segment:
|
||||
-
|
||||
name: "default_name_18"
|
||||
type: "any"
|
||||
value: "<your_own_value>"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_23"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_25 (source system.object-tagging.tags.name)"
|
||||
template: "<your_own_value> (source firewall.address6-template.name)"
|
||||
type: "ipprefix"
|
||||
uuid: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_address6_data(json):
|
||||
option_list = ['cache_ttl', 'color', 'comment',
|
||||
'end_ip', 'fqdn', 'host',
|
||||
'host_type', 'ip6', 'list',
|
||||
'name', 'obj_id', 'sdn',
|
||||
'start_ip', 'subnet_segment', 'tagging',
|
||||
'template', 'type', 'uuid',
|
||||
'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_address6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_address6'] and data['firewall_address6']:
|
||||
state = data['firewall_address6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_address6_data = data['firewall_address6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_address6_data(firewall_address6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'address6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'address6',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_address6']:
|
||||
resp = firewall_address6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_address6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"cache_ttl": {"required": False, "type": "int"},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"end_ip": {"required": False, "type": "str"},
|
||||
"fqdn": {"required": False, "type": "str"},
|
||||
"host": {"required": False, "type": "str"},
|
||||
"host_type": {"required": False, "type": "str",
|
||||
"choices": ["any", "specific"]},
|
||||
"ip6": {"required": False, "type": "str"},
|
||||
"list": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"ip": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"obj_id": {"required": False, "type": "str"},
|
||||
"sdn": {"required": False, "type": "str",
|
||||
"choices": ["nsx"]},
|
||||
"start_ip": {"required": False, "type": "str"},
|
||||
"subnet_segment": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["any", "specific"]},
|
||||
"value": {"required": False, "type": "str"}
|
||||
}},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"template": {"required": False, "type": "str"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["ipprefix", "iprange", "fqdn",
|
||||
"dynamic", "template"]},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,406 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_address6_template
|
||||
short_description: Configure IPv6 address templates in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and address6_template category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_address6_template:
|
||||
description:
|
||||
- Configure IPv6 address templates.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
ip6:
|
||||
description:
|
||||
- IPv6 address prefix.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- IPv6 address template name.
|
||||
required: true
|
||||
type: str
|
||||
subnet_segment:
|
||||
description:
|
||||
- IPv6 subnet segments.
|
||||
type: list
|
||||
suboptions:
|
||||
bits:
|
||||
description:
|
||||
- Number of bits.
|
||||
type: int
|
||||
exclusive:
|
||||
description:
|
||||
- Enable/disable exclusive value.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
id:
|
||||
description:
|
||||
- Subnet segment ID.
|
||||
required: true
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Subnet segment name.
|
||||
type: str
|
||||
values:
|
||||
description:
|
||||
- Subnet segment values.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Subnet segment value name.
|
||||
required: true
|
||||
type: str
|
||||
value:
|
||||
description:
|
||||
- Subnet segment value.
|
||||
type: str
|
||||
subnet_segment_count:
|
||||
description:
|
||||
- Number of IPv6 subnet segments.
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 address templates.
|
||||
fortios_firewall_address6_template:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_address6_template:
|
||||
ip6: "<your_own_value>"
|
||||
name: "default_name_4"
|
||||
subnet_segment:
|
||||
-
|
||||
bits: "6"
|
||||
exclusive: "enable"
|
||||
id: "8"
|
||||
name: "default_name_9"
|
||||
values:
|
||||
-
|
||||
name: "default_name_11"
|
||||
value: "<your_own_value>"
|
||||
subnet_segment_count: "13"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_address6_template_data(json):
|
||||
option_list = ['ip6', 'name', 'subnet_segment',
|
||||
'subnet_segment_count']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_address6_template(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_address6_template'] and data['firewall_address6_template']:
|
||||
state = data['firewall_address6_template']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_address6_template_data = data['firewall_address6_template']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_address6_template_data(firewall_address6_template_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'address6-template',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'address6-template',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_address6_template']:
|
||||
resp = firewall_address6_template(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_address6_template": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"ip6": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"subnet_segment": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"bits": {"required": False, "type": "int"},
|
||||
"exclusive": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"name": {"required": False, "type": "str"},
|
||||
"values": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"},
|
||||
"value": {"required": False, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"subnet_segment_count": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,428 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_addrgrp
|
||||
short_description: Configure IPv4 address groups in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and addrgrp category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_addrgrp:
|
||||
description:
|
||||
- Configure IPv4 address groups.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
allow_routing:
|
||||
description:
|
||||
- Enable/disable use of this group in the static route configuration.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
member:
|
||||
description:
|
||||
- Address objects contained within the group.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Address group name.
|
||||
required: true
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable address visibility in the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv4 address groups.
|
||||
fortios_firewall_addrgrp:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_addrgrp:
|
||||
allow_routing: "enable"
|
||||
color: "4"
|
||||
comment: "Comment."
|
||||
member:
|
||||
-
|
||||
name: "default_name_7 (source firewall.address.name firewall.addrgrp.name)"
|
||||
name: "default_name_8"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_11"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_13 (source system.object-tagging.tags.name)"
|
||||
uuid: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_addrgrp_data(json):
|
||||
option_list = ['allow_routing', 'color', 'comment',
|
||||
'member', 'name', 'tagging',
|
||||
'uuid', 'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_addrgrp(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_addrgrp'] and data['firewall_addrgrp']:
|
||||
state = data['firewall_addrgrp']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_addrgrp_data = data['firewall_addrgrp']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_addrgrp_data(firewall_addrgrp_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'addrgrp',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'addrgrp',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_addrgrp']:
|
||||
resp = firewall_addrgrp(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_addrgrp": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"allow_routing": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"member": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,418 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_addrgrp6
|
||||
short_description: Configure IPv6 address groups in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and addrgrp6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_addrgrp6:
|
||||
description:
|
||||
- Configure IPv6 address groups.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Integer value to determine the color of the icon in the GUI (1 - 32).
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
member:
|
||||
description:
|
||||
- Address objects contained within the group.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address6/addrgrp6 name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- IPv6 address group name.
|
||||
required: true
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable address group6 visibility in the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 address groups.
|
||||
fortios_firewall_addrgrp6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_addrgrp6:
|
||||
color: "3"
|
||||
comment: "Comment."
|
||||
member:
|
||||
-
|
||||
name: "default_name_6 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
name: "default_name_7"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_10"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_12 (source system.object-tagging.tags.name)"
|
||||
uuid: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_addrgrp6_data(json):
|
||||
option_list = ['color', 'comment', 'member',
|
||||
'name', 'tagging', 'uuid',
|
||||
'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_addrgrp6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_addrgrp6'] and data['firewall_addrgrp6']:
|
||||
state = data['firewall_addrgrp6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_addrgrp6_data = data['firewall_addrgrp6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_addrgrp6_data(firewall_addrgrp6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'addrgrp6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'addrgrp6',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_addrgrp6']:
|
||||
resp = firewall_addrgrp6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_addrgrp6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"member": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,320 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_auth_portal
|
||||
short_description: Configure firewall authentication portals in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and auth_portal category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
firewall_auth_portal:
|
||||
description:
|
||||
- Configure firewall authentication portals.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
groups:
|
||||
description:
|
||||
- Firewall user groups permitted to authenticate through this portal. Separate group names with spaces.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Group name. Source user.group.name.
|
||||
required: true
|
||||
type: str
|
||||
identity_based_route:
|
||||
description:
|
||||
- Name of the identity-based route that applies to this portal. Source firewall.identity-based-route.name.
|
||||
type: str
|
||||
portal_addr:
|
||||
description:
|
||||
- Address (or FQDN) of the authentication portal.
|
||||
type: str
|
||||
portal_addr6:
|
||||
description:
|
||||
- IPv6 address (or FQDN) of authentication portal.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure firewall authentication portals.
|
||||
fortios_firewall_auth_portal:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
firewall_auth_portal:
|
||||
groups:
|
||||
-
|
||||
name: "default_name_4 (source user.group.name)"
|
||||
identity_based_route: "<your_own_value> (source firewall.identity-based-route.name)"
|
||||
portal_addr: "<your_own_value>"
|
||||
portal_addr6: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_auth_portal_data(json):
|
||||
option_list = ['groups', 'identity_based_route', 'portal_addr',
|
||||
'portal_addr6']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_auth_portal(data, fos):
|
||||
vdom = data['vdom']
|
||||
firewall_auth_portal_data = data['firewall_auth_portal']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_auth_portal_data(firewall_auth_portal_data))
|
||||
|
||||
return fos.set('firewall',
|
||||
'auth-portal',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_auth_portal']:
|
||||
resp = firewall_auth_portal(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"firewall_auth_portal": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"groups": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"identity_based_route": {"required": False, "type": "str"},
|
||||
"portal_addr": {"required": False, "type": "str"},
|
||||
"portal_addr6": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,463 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_central_snat_map
|
||||
short_description: Configure central SNAT policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and central_snat_map category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_central_snat_map:
|
||||
description:
|
||||
- Configure central SNAT policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dst_addr:
|
||||
description:
|
||||
- Destination address name from available addresses.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- Destination interface name from available interfaces.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Interface name. Source system.interface.name system.zone.name.
|
||||
required: true
|
||||
type: str
|
||||
nat:
|
||||
description:
|
||||
- Enable/disable source NAT.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
nat_ippool:
|
||||
description:
|
||||
- Name of the IP pools to be used to translate addresses from available IP Pools.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- IP pool name. Source firewall.ippool.name.
|
||||
required: true
|
||||
type: str
|
||||
nat_port:
|
||||
description:
|
||||
- Translated port or port range (0 to 65535).
|
||||
type: str
|
||||
orig_addr:
|
||||
description:
|
||||
- Original address.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
orig_port:
|
||||
description:
|
||||
- Original TCP port (0 to 65535).
|
||||
type: str
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type (0 - 255).
|
||||
type: int
|
||||
srcintf:
|
||||
description:
|
||||
- Source interface name from available interfaces.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Interface name. Source system.interface.name system.zone.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable the active status of this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure central SNAT policies.
|
||||
fortios_firewall_central_snat_map:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_central_snat_map:
|
||||
comments: "<your_own_value>"
|
||||
dst_addr:
|
||||
-
|
||||
name: "default_name_5 (source firewall.address.name firewall.addrgrp.name)"
|
||||
dstintf:
|
||||
-
|
||||
name: "default_name_7 (source system.interface.name system.zone.name)"
|
||||
nat: "disable"
|
||||
nat_ippool:
|
||||
-
|
||||
name: "default_name_10 (source firewall.ippool.name)"
|
||||
nat_port: "<your_own_value>"
|
||||
orig_addr:
|
||||
-
|
||||
name: "default_name_13 (source firewall.address.name firewall.addrgrp.name)"
|
||||
orig_port: "<your_own_value>"
|
||||
policyid: "15"
|
||||
protocol: "16"
|
||||
srcintf:
|
||||
-
|
||||
name: "default_name_18 (source system.interface.name system.zone.name)"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_central_snat_map_data(json):
|
||||
option_list = ['comments', 'dst_addr', 'dstintf',
|
||||
'nat', 'nat_ippool', 'nat_port',
|
||||
'orig_addr', 'orig_port', 'policyid',
|
||||
'protocol', 'srcintf', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_central_snat_map(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_central_snat_map'] and data['firewall_central_snat_map']:
|
||||
state = data['firewall_central_snat_map']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_central_snat_map_data = data['firewall_central_snat_map']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_central_snat_map_data(firewall_central_snat_map_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'central-snat-map',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'central-snat-map',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_central_snat_map']:
|
||||
resp = firewall_central_snat_map(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_central_snat_map": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dst_addr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"nat": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"nat_ippool": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"nat_port": {"required": False, "type": "str"},
|
||||
"orig_addr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"orig_port": {"required": False, "type": "str"},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"protocol": {"required": False, "type": "int"},
|
||||
"srcintf": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,352 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_dnstranslation
|
||||
short_description: Configure DNS translation in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and dnstranslation category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_dnstranslation:
|
||||
description:
|
||||
- Configure DNS translation.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
dst:
|
||||
description:
|
||||
- IPv4 address or subnet on the external network to substitute for the resolved address in DNS query replies. Can be single IP address or
|
||||
subnet on the external network, but number of addresses must equal number of mapped IP addresses in src.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
netmask:
|
||||
description:
|
||||
- If src and dst are subnets rather than single IP addresses, enter the netmask for both src and dst.
|
||||
type: str
|
||||
src:
|
||||
description:
|
||||
- IPv4 address or subnet on the internal network to compare with the resolved address in DNS query replies. If the resolved address
|
||||
matches, the resolved address is substituted with dst.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure DNS translation.
|
||||
fortios_firewall_dnstranslation:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_dnstranslation:
|
||||
dst: "<your_own_value>"
|
||||
id: "4"
|
||||
netmask: "<your_own_value>"
|
||||
src: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_dnstranslation_data(json):
|
||||
option_list = ['dst', 'id', 'netmask',
|
||||
'src']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_dnstranslation(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_dnstranslation'] and data['firewall_dnstranslation']:
|
||||
state = data['firewall_dnstranslation']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_dnstranslation_data = data['firewall_dnstranslation']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_dnstranslation_data(firewall_dnstranslation_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'dnstranslation',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'dnstranslation',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_dnstranslation']:
|
||||
resp = firewall_dnstranslation(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_dnstranslation": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"dst": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"netmask": {"required": False, "type": "str"},
|
||||
"src": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,383 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_identity_based_route
|
||||
short_description: Configure identity based routing in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and identity_based_route category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_identity_based_route:
|
||||
description:
|
||||
- Configure identity based routing.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comments:
|
||||
description:
|
||||
- Comments.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Name.
|
||||
required: true
|
||||
type: str
|
||||
rule:
|
||||
description:
|
||||
- Rule.
|
||||
type: list
|
||||
suboptions:
|
||||
device:
|
||||
description:
|
||||
- Outgoing interface for the rule. Source system.interface.name.
|
||||
type: str
|
||||
gateway:
|
||||
description:
|
||||
- "IPv4 address of the gateway (Format: xxx.xxx.xxx.xxx )."
|
||||
type: str
|
||||
groups:
|
||||
description:
|
||||
- Select one or more group(s) from available groups that are allowed to use this route. Separate group names with a space.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Group name. Source user.group.name.
|
||||
required: true
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Rule ID.
|
||||
required: true
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure identity based routing.
|
||||
fortios_firewall_identity_based_route:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_identity_based_route:
|
||||
comments: "<your_own_value>"
|
||||
name: "default_name_4"
|
||||
rule:
|
||||
-
|
||||
device: "<your_own_value> (source system.interface.name)"
|
||||
gateway: "<your_own_value>"
|
||||
groups:
|
||||
-
|
||||
name: "default_name_9 (source user.group.name)"
|
||||
id: "10"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_identity_based_route_data(json):
|
||||
option_list = ['comments', 'name', 'rule']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_identity_based_route(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_identity_based_route'] and data['firewall_identity_based_route']:
|
||||
state = data['firewall_identity_based_route']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_identity_based_route_data = data['firewall_identity_based_route']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_identity_based_route_data(firewall_identity_based_route_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'identity-based-route',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'identity-based-route',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_identity_based_route']:
|
||||
resp = firewall_identity_based_route(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_identity_based_route": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"rule": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"device": {"required": False, "type": "str"},
|
||||
"gateway": {"required": False, "type": "str"},
|
||||
"groups": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"}
|
||||
}}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,555 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_interface_policy
|
||||
short_description: Configure IPv4 interface policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and interface_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_interface_policy:
|
||||
description:
|
||||
- Configure IPv4 interface policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
address_type:
|
||||
description:
|
||||
- Policy address type (IPv4 or IPv6).
|
||||
type: str
|
||||
choices:
|
||||
- ipv4
|
||||
- ipv6
|
||||
application_list:
|
||||
description:
|
||||
- Application list name. Source application.list.name.
|
||||
type: str
|
||||
application_list_status:
|
||||
description:
|
||||
- Enable/disable application control.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
av_profile:
|
||||
description:
|
||||
- Antivirus profile. Source antivirus.profile.name.
|
||||
type: str
|
||||
av_profile_status:
|
||||
description:
|
||||
- Enable/disable antivirus.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
comments:
|
||||
description:
|
||||
- Comments.
|
||||
type: str
|
||||
dlp_sensor:
|
||||
description:
|
||||
- DLP sensor name. Source dlp.sensor.name.
|
||||
type: str
|
||||
dlp_sensor_status:
|
||||
description:
|
||||
- Enable/disable DLP.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dsri:
|
||||
description:
|
||||
- Enable/disable DSRI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dstaddr:
|
||||
description:
|
||||
- Address object to limit traffic monitoring to network traffic sent to the specified address or range.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
interface:
|
||||
description:
|
||||
- Monitored interface name from available interfaces. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
ips_sensor:
|
||||
description:
|
||||
- IPS sensor name. Source ips.sensor.name.
|
||||
type: str
|
||||
ips_sensor_status:
|
||||
description:
|
||||
- Enable/disable IPS.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
label:
|
||||
description:
|
||||
- Label.
|
||||
type: str
|
||||
logtraffic:
|
||||
description:
|
||||
- "Logging type to be used in this policy (Options: all | utm | disable)."
|
||||
type: str
|
||||
choices:
|
||||
- all
|
||||
- utm
|
||||
- disable
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
scan_botnet_connections:
|
||||
description:
|
||||
- Enable/disable scanning for connections to Botnet servers.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- block
|
||||
- monitor
|
||||
service:
|
||||
description:
|
||||
- Service object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
spamfilter_profile:
|
||||
description:
|
||||
- Antispam profile. Source spamfilter.profile.name.
|
||||
type: str
|
||||
spamfilter_profile_status:
|
||||
description:
|
||||
- Enable/disable antispam.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
srcaddr:
|
||||
description:
|
||||
- Address object to limit traffic monitoring to network traffic sent from the specified address or range.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
webfilter_profile:
|
||||
description:
|
||||
- Web filter profile. Source webfilter.profile.name.
|
||||
type: str
|
||||
webfilter_profile_status:
|
||||
description:
|
||||
- Enable/disable web filtering.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv4 interface policies.
|
||||
fortios_firewall_interface_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_interface_policy:
|
||||
address_type: "ipv4"
|
||||
application_list: "<your_own_value> (source application.list.name)"
|
||||
application_list_status: "enable"
|
||||
av_profile: "<your_own_value> (source antivirus.profile.name)"
|
||||
av_profile_status: "enable"
|
||||
comments: "<your_own_value>"
|
||||
dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
|
||||
dlp_sensor_status: "enable"
|
||||
dsri: "enable"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_13 (source firewall.address.name firewall.addrgrp.name)"
|
||||
interface: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
ips_sensor: "<your_own_value> (source ips.sensor.name)"
|
||||
ips_sensor_status: "enable"
|
||||
label: "<your_own_value>"
|
||||
logtraffic: "all"
|
||||
policyid: "19"
|
||||
scan_botnet_connections: "disable"
|
||||
service:
|
||||
-
|
||||
name: "default_name_22 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
|
||||
spamfilter_profile_status: "enable"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_26 (source firewall.address.name firewall.addrgrp.name)"
|
||||
status: "enable"
|
||||
webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
|
||||
webfilter_profile_status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_interface_policy_data(json):
|
||||
option_list = ['address_type', 'application_list', 'application_list_status',
|
||||
'av_profile', 'av_profile_status', 'comments',
|
||||
'dlp_sensor', 'dlp_sensor_status', 'dsri',
|
||||
'dstaddr', 'interface', 'ips_sensor',
|
||||
'ips_sensor_status', 'label', 'logtraffic',
|
||||
'policyid', 'scan_botnet_connections', 'service',
|
||||
'spamfilter_profile', 'spamfilter_profile_status', 'srcaddr',
|
||||
'status', 'webfilter_profile', 'webfilter_profile_status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_interface_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_interface_policy'] and data['firewall_interface_policy']:
|
||||
state = data['firewall_interface_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_interface_policy_data = data['firewall_interface_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_interface_policy_data(firewall_interface_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'interface-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'interface-policy',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_interface_policy']:
|
||||
resp = firewall_interface_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_interface_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"address_type": {"required": False, "type": "str",
|
||||
"choices": ["ipv4", "ipv6"]},
|
||||
"application_list": {"required": False, "type": "str"},
|
||||
"application_list_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"av_profile": {"required": False, "type": "str"},
|
||||
"av_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dlp_sensor": {"required": False, "type": "str"},
|
||||
"dlp_sensor_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dsri": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"interface": {"required": False, "type": "str"},
|
||||
"ips_sensor": {"required": False, "type": "str"},
|
||||
"ips_sensor_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"label": {"required": False, "type": "str"},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["all", "utm", "disable"]},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"scan_botnet_connections": {"required": False, "type": "str",
|
||||
"choices": ["disable", "block", "monitor"]},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"spamfilter_profile": {"required": False, "type": "str"},
|
||||
"spamfilter_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"webfilter_profile": {"required": False, "type": "str"},
|
||||
"webfilter_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,555 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_interface_policy6
|
||||
short_description: Configure IPv6 interface policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and interface_policy6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_interface_policy6:
|
||||
description:
|
||||
- Configure IPv6 interface policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
address_type:
|
||||
description:
|
||||
- Policy address type (IPv4 or IPv6).
|
||||
type: str
|
||||
choices:
|
||||
- ipv4
|
||||
- ipv6
|
||||
application_list:
|
||||
description:
|
||||
- Application list name. Source application.list.name.
|
||||
type: str
|
||||
application_list_status:
|
||||
description:
|
||||
- Enable/disable application control.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
av_profile:
|
||||
description:
|
||||
- Antivirus profile. Source antivirus.profile.name.
|
||||
type: str
|
||||
av_profile_status:
|
||||
description:
|
||||
- Enable/disable antivirus.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
comments:
|
||||
description:
|
||||
- Comments.
|
||||
type: str
|
||||
dlp_sensor:
|
||||
description:
|
||||
- DLP sensor name. Source dlp.sensor.name.
|
||||
type: str
|
||||
dlp_sensor_status:
|
||||
description:
|
||||
- Enable/disable DLP.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dsri:
|
||||
description:
|
||||
- Enable/disable DSRI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dstaddr6:
|
||||
description:
|
||||
- IPv6 address object to limit traffic monitoring to network traffic sent to the specified address or range.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
interface:
|
||||
description:
|
||||
- Monitored interface name from available interfaces. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
ips_sensor:
|
||||
description:
|
||||
- IPS sensor name. Source ips.sensor.name.
|
||||
type: str
|
||||
ips_sensor_status:
|
||||
description:
|
||||
- Enable/disable IPS.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
label:
|
||||
description:
|
||||
- Label.
|
||||
type: str
|
||||
logtraffic:
|
||||
description:
|
||||
- "Logging type to be used in this policy (Options: all | utm | disable)."
|
||||
type: str
|
||||
choices:
|
||||
- all
|
||||
- utm
|
||||
- disable
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
scan_botnet_connections:
|
||||
description:
|
||||
- Enable/disable scanning for connections to Botnet servers.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- block
|
||||
- monitor
|
||||
service6:
|
||||
description:
|
||||
- Service name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
spamfilter_profile:
|
||||
description:
|
||||
- Antispam profile. Source spamfilter.profile.name.
|
||||
type: str
|
||||
spamfilter_profile_status:
|
||||
description:
|
||||
- Enable/disable antispam.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
srcaddr6:
|
||||
description:
|
||||
- IPv6 address object to limit traffic monitoring to network traffic sent from the specified address or range.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
webfilter_profile:
|
||||
description:
|
||||
- Web filter profile. Source webfilter.profile.name.
|
||||
type: str
|
||||
webfilter_profile_status:
|
||||
description:
|
||||
- Enable/disable web filtering.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 interface policies.
|
||||
fortios_firewall_interface_policy6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_interface_policy6:
|
||||
address_type: "ipv4"
|
||||
application_list: "<your_own_value> (source application.list.name)"
|
||||
application_list_status: "enable"
|
||||
av_profile: "<your_own_value> (source antivirus.profile.name)"
|
||||
av_profile_status: "enable"
|
||||
comments: "<your_own_value>"
|
||||
dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
|
||||
dlp_sensor_status: "enable"
|
||||
dsri: "enable"
|
||||
dstaddr6:
|
||||
-
|
||||
name: "default_name_13 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
interface: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
ips_sensor: "<your_own_value> (source ips.sensor.name)"
|
||||
ips_sensor_status: "enable"
|
||||
label: "<your_own_value>"
|
||||
logtraffic: "all"
|
||||
policyid: "19"
|
||||
scan_botnet_connections: "disable"
|
||||
service6:
|
||||
-
|
||||
name: "default_name_22 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
|
||||
spamfilter_profile_status: "enable"
|
||||
srcaddr6:
|
||||
-
|
||||
name: "default_name_26 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
status: "enable"
|
||||
webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
|
||||
webfilter_profile_status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_interface_policy6_data(json):
|
||||
option_list = ['address_type', 'application_list', 'application_list_status',
|
||||
'av_profile', 'av_profile_status', 'comments',
|
||||
'dlp_sensor', 'dlp_sensor_status', 'dsri',
|
||||
'dstaddr6', 'interface', 'ips_sensor',
|
||||
'ips_sensor_status', 'label', 'logtraffic',
|
||||
'policyid', 'scan_botnet_connections', 'service6',
|
||||
'spamfilter_profile', 'spamfilter_profile_status', 'srcaddr6',
|
||||
'status', 'webfilter_profile', 'webfilter_profile_status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_interface_policy6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_interface_policy6'] and data['firewall_interface_policy6']:
|
||||
state = data['firewall_interface_policy6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_interface_policy6_data = data['firewall_interface_policy6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_interface_policy6_data(firewall_interface_policy6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'interface-policy6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'interface-policy6',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_interface_policy6']:
|
||||
resp = firewall_interface_policy6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_interface_policy6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"address_type": {"required": False, "type": "str",
|
||||
"choices": ["ipv4", "ipv6"]},
|
||||
"application_list": {"required": False, "type": "str"},
|
||||
"application_list_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"av_profile": {"required": False, "type": "str"},
|
||||
"av_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dlp_sensor": {"required": False, "type": "str"},
|
||||
"dlp_sensor_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dsri": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dstaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"interface": {"required": False, "type": "str"},
|
||||
"ips_sensor": {"required": False, "type": "str"},
|
||||
"ips_sensor_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"label": {"required": False, "type": "str"},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["all", "utm", "disable"]},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"scan_botnet_connections": {"required": False, "type": "str",
|
||||
"choices": ["disable", "block", "monitor"]},
|
||||
"service6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"spamfilter_profile": {"required": False, "type": "str"},
|
||||
"spamfilter_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"srcaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"webfilter_profile": {"required": False, "type": "str"},
|
||||
"webfilter_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,425 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_internet_service
|
||||
short_description: Show Internet Service application in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and internet_service category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_internet_service:
|
||||
description:
|
||||
- Show Internet Service application.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
database:
|
||||
description:
|
||||
- Database name this Internet Service belongs to.
|
||||
type: str
|
||||
choices:
|
||||
- isdb
|
||||
- irdb
|
||||
direction:
|
||||
description:
|
||||
- How this service may be used in a firewall policy (source, destination or both).
|
||||
type: str
|
||||
choices:
|
||||
- src
|
||||
- dst
|
||||
- both
|
||||
entry:
|
||||
description:
|
||||
- Entries in the Internet Service database.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Entry ID.
|
||||
required: true
|
||||
type: int
|
||||
ip_number:
|
||||
description:
|
||||
- Total number of IP addresses.
|
||||
type: int
|
||||
ip_range_number:
|
||||
description:
|
||||
- Total number of IP ranges.
|
||||
type: int
|
||||
port:
|
||||
description:
|
||||
- Integer value for the TCP/IP port (0 - 65535).
|
||||
type: int
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type as defined by IANA (0 - 255).
|
||||
type: int
|
||||
icon_id:
|
||||
description:
|
||||
- Icon ID of Internet Service.
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- Internet Service ID.
|
||||
required: true
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Internet Service name.
|
||||
type: str
|
||||
offset:
|
||||
description:
|
||||
- Offset of Internet Service ID.
|
||||
type: int
|
||||
reputation:
|
||||
description:
|
||||
- Reputation level of the Internet Service.
|
||||
type: int
|
||||
sld_id:
|
||||
description:
|
||||
- Second Level Domain.
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Show Internet Service application.
|
||||
fortios_firewall_internet_service:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_internet_service:
|
||||
database: "isdb"
|
||||
direction: "src"
|
||||
entry:
|
||||
-
|
||||
id: "6"
|
||||
ip_number: "7"
|
||||
ip_range_number: "8"
|
||||
port: "9"
|
||||
protocol: "10"
|
||||
icon_id: "11"
|
||||
id: "12"
|
||||
name: "default_name_13"
|
||||
offset: "14"
|
||||
reputation: "15"
|
||||
sld_id: "16"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_internet_service_data(json):
|
||||
option_list = ['database', 'direction', 'entry',
|
||||
'icon_id', 'id', 'name',
|
||||
'offset', 'reputation', 'sld_id']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_internet_service(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_internet_service'] and data['firewall_internet_service']:
|
||||
state = data['firewall_internet_service']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_internet_service_data = data['firewall_internet_service']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_internet_service_data(firewall_internet_service_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'internet-service',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'internet-service',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_internet_service']:
|
||||
resp = firewall_internet_service(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_internet_service": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"database": {"required": False, "type": "str",
|
||||
"choices": ["isdb", "irdb"]},
|
||||
"direction": {"required": False, "type": "str",
|
||||
"choices": ["src", "dst", "both"]},
|
||||
"entry": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"},
|
||||
"ip_number": {"required": False, "type": "int"},
|
||||
"ip_range_number": {"required": False, "type": "int"},
|
||||
"port": {"required": False, "type": "int"},
|
||||
"protocol": {"required": False, "type": "int"}
|
||||
}},
|
||||
"icon_id": {"required": False, "type": "int"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"name": {"required": False, "type": "str"},
|
||||
"offset": {"required": False, "type": "int"},
|
||||
"reputation": {"required": False, "type": "int"},
|
||||
"sld_id": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,472 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_internet_service_custom
|
||||
short_description: Configure custom Internet Services in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and internet_service_custom category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_internet_service_custom:
|
||||
description:
|
||||
- Configure custom Internet Services.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
disable_entry:
|
||||
description:
|
||||
- Disable entries in the Internet Service database.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Disable entry ID.
|
||||
required: true
|
||||
type: int
|
||||
ip_range:
|
||||
description:
|
||||
- IP ranges in the disable entry.
|
||||
type: list
|
||||
suboptions:
|
||||
end_ip:
|
||||
description:
|
||||
- End IP address.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Disable entry range ID.
|
||||
required: true
|
||||
type: int
|
||||
start_ip:
|
||||
description:
|
||||
- Start IP address.
|
||||
type: str
|
||||
port:
|
||||
description:
|
||||
- Integer value for the TCP/IP port (0 - 65535).
|
||||
type: int
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type as defined by IANA (0 - 255).
|
||||
type: int
|
||||
entry:
|
||||
description:
|
||||
- Entries added to the Internet Service database and custom database.
|
||||
type: list
|
||||
suboptions:
|
||||
dst:
|
||||
description:
|
||||
- Destination address or address group name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Select the destination address or address group object from available options. Source firewall.address.name firewall
|
||||
.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Entry ID(1-255).
|
||||
required: true
|
||||
type: int
|
||||
port_range:
|
||||
description:
|
||||
- Port ranges in the custom entry.
|
||||
type: list
|
||||
suboptions:
|
||||
end_port:
|
||||
description:
|
||||
- Integer value for ending TCP/UDP/SCTP destination port in range (1 to 65535).
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- Custom entry port range ID.
|
||||
required: true
|
||||
type: int
|
||||
start_port:
|
||||
description:
|
||||
- Integer value for starting TCP/UDP/SCTP destination port in range (1 to 65535).
|
||||
type: int
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type as defined by IANA (0 - 255).
|
||||
type: int
|
||||
master_service_id:
|
||||
description:
|
||||
- Internet Service ID in the Internet Service database. Source firewall.internet-service.id.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Internet Service name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure custom Internet Services.
|
||||
fortios_firewall_internet_service_custom:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_internet_service_custom:
|
||||
comment: "Comment."
|
||||
disable_entry:
|
||||
-
|
||||
id: "5"
|
||||
ip_range:
|
||||
-
|
||||
end_ip: "<your_own_value>"
|
||||
id: "8"
|
||||
start_ip: "<your_own_value>"
|
||||
port: "10"
|
||||
protocol: "11"
|
||||
entry:
|
||||
-
|
||||
dst:
|
||||
-
|
||||
name: "default_name_14 (source firewall.address.name firewall.addrgrp.name)"
|
||||
id: "15"
|
||||
port_range:
|
||||
-
|
||||
end_port: "17"
|
||||
id: "18"
|
||||
start_port: "19"
|
||||
protocol: "20"
|
||||
master_service_id: "21 (source firewall.internet-service.id)"
|
||||
name: "default_name_22"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_internet_service_custom_data(json):
|
||||
option_list = ['comment', 'disable_entry', 'entry',
|
||||
'master_service_id', 'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_internet_service_custom(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_internet_service_custom'] and data['firewall_internet_service_custom']:
|
||||
state = data['firewall_internet_service_custom']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_internet_service_custom_data = data['firewall_internet_service_custom']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_internet_service_custom_data(firewall_internet_service_custom_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'internet-service-custom',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'internet-service-custom',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_internet_service_custom']:
|
||||
resp = firewall_internet_service_custom(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_internet_service_custom": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"disable_entry": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"},
|
||||
"ip_range": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"end_ip": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"start_ip": {"required": False, "type": "str"}
|
||||
}},
|
||||
"port": {"required": False, "type": "int"},
|
||||
"protocol": {"required": False, "type": "int"}
|
||||
}},
|
||||
"entry": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"dst": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"port_range": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"end_port": {"required": False, "type": "int"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"start_port": {"required": False, "type": "int"}
|
||||
}},
|
||||
"protocol": {"required": False, "type": "int"}
|
||||
}},
|
||||
"master_service_id": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,354 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_internet_service_group
|
||||
short_description: Configure group of Internet Service in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and internet_service_group category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_internet_service_group:
|
||||
description:
|
||||
- Configure group of Internet Service.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
member:
|
||||
description:
|
||||
- Internet Service group member.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Internet Service ID. Source firewall.internet-service.id.
|
||||
required: true
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Internet Service group name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure group of Internet Service.
|
||||
fortios_firewall_internet_service_group:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_internet_service_group:
|
||||
comment: "Comment."
|
||||
member:
|
||||
-
|
||||
id: "5 (source firewall.internet-service.id)"
|
||||
name: "default_name_6"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_internet_service_group_data(json):
|
||||
option_list = ['comment', 'member', 'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_internet_service_group(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_internet_service_group'] and data['firewall_internet_service_group']:
|
||||
state = data['firewall_internet_service_group']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_internet_service_group_data = data['firewall_internet_service_group']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_internet_service_group_data(firewall_internet_service_group_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'internet-service-group',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'internet-service-group',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_internet_service_group']:
|
||||
resp = firewall_internet_service_group(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_internet_service_group": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"member": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,359 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ip_translation
|
||||
short_description: Configure firewall IP-translation in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ip_translation category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ip_translation:
|
||||
description:
|
||||
- Configure firewall IP-translation.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
endip:
|
||||
description:
|
||||
- "Final IPv4 address (inclusive) in the range of the addresses to be translated (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
map_startip:
|
||||
description:
|
||||
- "Address to be used as the starting point for translation in the range (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
startip:
|
||||
description:
|
||||
- "First IPv4 address (inclusive) in the range of the addresses to be translated (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
transid:
|
||||
description:
|
||||
- IP translation ID.
|
||||
required: true
|
||||
type: int
|
||||
type:
|
||||
description:
|
||||
- "IP translation type (option: SCTP)."
|
||||
type: str
|
||||
choices:
|
||||
- SCTP
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure firewall IP-translation.
|
||||
fortios_firewall_ip_translation:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ip_translation:
|
||||
endip: "<your_own_value>"
|
||||
map_startip: "<your_own_value>"
|
||||
startip: "<your_own_value>"
|
||||
transid: "6"
|
||||
type: "SCTP"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ip_translation_data(json):
|
||||
option_list = ['endip', 'map_startip', 'startip',
|
||||
'transid', 'type']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ip_translation(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ip_translation'] and data['firewall_ip_translation']:
|
||||
state = data['firewall_ip_translation']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ip_translation_data = data['firewall_ip_translation']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ip_translation_data(firewall_ip_translation_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'ip-translation',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'ip-translation',
|
||||
mkey=filtered_data['transid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ip_translation']:
|
||||
resp = firewall_ip_translation(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ip_translation": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"endip": {"required": False, "type": "str"},
|
||||
"map_startip": {"required": False, "type": "str"},
|
||||
"startip": {"required": False, "type": "str"},
|
||||
"transid": {"required": True, "type": "int"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["SCTP"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,314 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ipmacbinding_setting
|
||||
short_description: Configure IP to MAC binding settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ipmacbinding feature and setting category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
firewall_ipmacbinding_setting:
|
||||
description:
|
||||
- Configure IP to MAC binding settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
bindthroughfw:
|
||||
description:
|
||||
- Enable/disable use of IP/MAC binding to filter packets that would normally go through the firewall.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
bindtofw:
|
||||
description:
|
||||
- Enable/disable use of IP/MAC binding to filter packets that would normally go to the firewall.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
undefinedhost:
|
||||
description:
|
||||
- Select action to take on packets with IP/MAC addresses not in the binding list .
|
||||
type: str
|
||||
choices:
|
||||
- allow
|
||||
- block
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IP to MAC binding settings.
|
||||
fortios_firewall_ipmacbinding_setting:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
firewall_ipmacbinding_setting:
|
||||
bindthroughfw: "enable"
|
||||
bindtofw: "enable"
|
||||
undefinedhost: "allow"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ipmacbinding_setting_data(json):
|
||||
option_list = ['bindthroughfw', 'bindtofw', 'undefinedhost']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ipmacbinding_setting(data, fos):
|
||||
vdom = data['vdom']
|
||||
firewall_ipmacbinding_setting_data = data['firewall_ipmacbinding_setting']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ipmacbinding_setting_data(firewall_ipmacbinding_setting_data))
|
||||
|
||||
return fos.set('firewall.ipmacbinding',
|
||||
'setting',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ipmacbinding(data, fos):
|
||||
|
||||
if data['firewall_ipmacbinding_setting']:
|
||||
resp = firewall_ipmacbinding_setting(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"firewall_ipmacbinding_setting": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"bindthroughfw": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"bindtofw": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"undefinedhost": {"required": False, "type": "str",
|
||||
"choices": ["allow", "block"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ipmacbinding(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ipmacbinding(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,359 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ipmacbinding_table
|
||||
short_description: Configure IP to MAC address pairs in the IP/MAC binding table in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ipmacbinding feature and table category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ipmacbinding_table:
|
||||
description:
|
||||
- Configure IP to MAC address pairs in the IP/MAC binding table.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
ip:
|
||||
description:
|
||||
- "IPv4 address portion of the pair (format: xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
mac:
|
||||
description:
|
||||
- "MAC address portion of the pair (format: xx:xx:xx:xx:xx:xx in hexidecimal)."
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Name of the pair (optional).
|
||||
type: str
|
||||
seq_num:
|
||||
description:
|
||||
- Entry number.
|
||||
type: int
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this IP-mac binding pair.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IP to MAC address pairs in the IP/MAC binding table.
|
||||
fortios_firewall_ipmacbinding_table:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ipmacbinding_table:
|
||||
ip: "<your_own_value>"
|
||||
mac: "<your_own_value>"
|
||||
name: "default_name_5"
|
||||
seq_num: "6"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ipmacbinding_table_data(json):
|
||||
option_list = ['ip', 'mac', 'name',
|
||||
'seq_num', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ipmacbinding_table(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ipmacbinding_table'] and data['firewall_ipmacbinding_table']:
|
||||
state = data['firewall_ipmacbinding_table']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ipmacbinding_table_data = data['firewall_ipmacbinding_table']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ipmacbinding_table_data(firewall_ipmacbinding_table_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.ipmacbinding',
|
||||
'table',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.ipmacbinding',
|
||||
'table',
|
||||
mkey=filtered_data['seq-num'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ipmacbinding(data, fos):
|
||||
|
||||
if data['firewall_ipmacbinding_table']:
|
||||
resp = firewall_ipmacbinding_table(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ipmacbinding_table": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"ip": {"required": False, "type": "str"},
|
||||
"mac": {"required": False, "type": "str"},
|
||||
"name": {"required": False, "type": "str"},
|
||||
"seq_num": {"required": False, "type": "int"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ipmacbinding(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ipmacbinding(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,428 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ippool
|
||||
short_description: Configure IPv4 IP pools in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ippool category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ippool:
|
||||
description:
|
||||
- Configure IPv4 IP pools.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
arp_intf:
|
||||
description:
|
||||
- Select an interface from available options that will reply to ARP requests. (If blank, any is selected). Source system.interface.name.
|
||||
type: str
|
||||
arp_reply:
|
||||
description:
|
||||
- Enable/disable replying to ARP requests when an IP Pool is added to a policy .
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
associated_interface:
|
||||
description:
|
||||
- Associated interface name. Source system.interface.name.
|
||||
type: str
|
||||
block_size:
|
||||
description:
|
||||
- Number of addresses in a block (64 to 4096).
|
||||
type: int
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
endip:
|
||||
description:
|
||||
- "Final IPv4 address (inclusive) in the range for the address pool (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- IP pool name.
|
||||
required: true
|
||||
type: str
|
||||
num_blocks_per_user:
|
||||
description:
|
||||
- Number of addresses blocks that can be used by a user (1 to 128).
|
||||
type: int
|
||||
pba_timeout:
|
||||
description:
|
||||
- Port block allocation timeout (seconds).
|
||||
type: int
|
||||
permit_any_host:
|
||||
description:
|
||||
- Enable/disable full cone NAT.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
source_endip:
|
||||
description:
|
||||
- "Final IPv4 address (inclusive) in the range of the source addresses to be translated (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
source_startip:
|
||||
description:
|
||||
- " First IPv4 address (inclusive) in the range of the source addresses to be translated (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
startip:
|
||||
description:
|
||||
- "First IPv4 address (inclusive) in the range for the address pool (format xxx.xxx.xxx.xxx)."
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- IP pool type (overload, one-to-one, fixed port range, or port block allocation).
|
||||
type: str
|
||||
choices:
|
||||
- overload
|
||||
- one-to-one
|
||||
- fixed-port-range
|
||||
- port-block-allocation
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv4 IP pools.
|
||||
fortios_firewall_ippool:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ippool:
|
||||
arp_intf: "<your_own_value> (source system.interface.name)"
|
||||
arp_reply: "disable"
|
||||
associated_interface: "<your_own_value> (source system.interface.name)"
|
||||
block_size: "6"
|
||||
comments: "<your_own_value>"
|
||||
endip: "<your_own_value>"
|
||||
name: "default_name_9"
|
||||
num_blocks_per_user: "10"
|
||||
pba_timeout: "11"
|
||||
permit_any_host: "disable"
|
||||
source_endip: "<your_own_value>"
|
||||
source_startip: "<your_own_value>"
|
||||
startip: "<your_own_value>"
|
||||
type: "overload"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ippool_data(json):
|
||||
option_list = ['arp_intf', 'arp_reply', 'associated_interface',
|
||||
'block_size', 'comments', 'endip',
|
||||
'name', 'num_blocks_per_user', 'pba_timeout',
|
||||
'permit_any_host', 'source_endip', 'source_startip',
|
||||
'startip', 'type']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ippool(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ippool'] and data['firewall_ippool']:
|
||||
state = data['firewall_ippool']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ippool_data = data['firewall_ippool']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ippool_data(firewall_ippool_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'ippool',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'ippool',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ippool']:
|
||||
resp = firewall_ippool(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ippool": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"arp_intf": {"required": False, "type": "str"},
|
||||
"arp_reply": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"associated_interface": {"required": False, "type": "str"},
|
||||
"block_size": {"required": False, "type": "int"},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"endip": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"num_blocks_per_user": {"required": False, "type": "int"},
|
||||
"pba_timeout": {"required": False, "type": "int"},
|
||||
"permit_any_host": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"source_endip": {"required": False, "type": "str"},
|
||||
"source_startip": {"required": False, "type": "str"},
|
||||
"startip": {"required": False, "type": "str"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["overload", "one-to-one", "fixed-port-range",
|
||||
"port-block-allocation"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,350 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ippool6
|
||||
short_description: Configure IPv6 IP pools in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ippool6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ippool6:
|
||||
description:
|
||||
- Configure IPv6 IP pools.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
endip:
|
||||
description:
|
||||
- "Final IPv6 address (inclusive) in the range for the address pool (format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx)."
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- IPv6 IP pool name.
|
||||
required: true
|
||||
type: str
|
||||
startip:
|
||||
description:
|
||||
- "First IPv6 address (inclusive) in the range for the address pool (format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx)."
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 IP pools.
|
||||
fortios_firewall_ippool6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ippool6:
|
||||
comments: "<your_own_value>"
|
||||
endip: "<your_own_value>"
|
||||
name: "default_name_5"
|
||||
startip: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ippool6_data(json):
|
||||
option_list = ['comments', 'endip', 'name',
|
||||
'startip']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ippool6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ippool6'] and data['firewall_ippool6']:
|
||||
state = data['firewall_ippool6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ippool6_data = data['firewall_ippool6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ippool6_data(firewall_ippool6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'ippool6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'ippool6',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ippool6']:
|
||||
resp = firewall_ippool6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ippool6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"endip": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"startip": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,358 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ipv6_eh_filter
|
||||
short_description: Configure IPv6 extension header filter in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ipv6_eh_filter category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
firewall_ipv6_eh_filter:
|
||||
description:
|
||||
- Configure IPv6 extension header filter.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
auth:
|
||||
description:
|
||||
- Enable/disable blocking packets with the Authentication header .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dest_opt:
|
||||
description:
|
||||
- Enable/disable blocking packets with Destination Options headers .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
fragment:
|
||||
description:
|
||||
- Enable/disable blocking packets with the Fragment header .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
hdopt_type:
|
||||
description:
|
||||
- Block specific Hop-by-Hop and/or Destination Option types (max. 7 types, each between 0 and 255).
|
||||
type: int
|
||||
hop_opt:
|
||||
description:
|
||||
- Enable/disable blocking packets with the Hop-by-Hop Options header .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
no_next:
|
||||
description:
|
||||
- Enable/disable blocking packets with the No Next header
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
routing:
|
||||
description:
|
||||
- Enable/disable blocking packets with Routing headers .
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
routing_type:
|
||||
description:
|
||||
- Block specific Routing header types (max. 7 types, each between 0 and 255).
|
||||
type: int
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 extension header filter.
|
||||
fortios_firewall_ipv6_eh_filter:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
firewall_ipv6_eh_filter:
|
||||
auth: "enable"
|
||||
dest_opt: "enable"
|
||||
fragment: "enable"
|
||||
hdopt_type: "6"
|
||||
hop_opt: "enable"
|
||||
no_next: "enable"
|
||||
routing: "enable"
|
||||
routing_type: "10"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ipv6_eh_filter_data(json):
|
||||
option_list = ['auth', 'dest_opt', 'fragment',
|
||||
'hdopt_type', 'hop_opt', 'no_next',
|
||||
'routing', 'routing_type']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ipv6_eh_filter(data, fos):
|
||||
vdom = data['vdom']
|
||||
firewall_ipv6_eh_filter_data = data['firewall_ipv6_eh_filter']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ipv6_eh_filter_data(firewall_ipv6_eh_filter_data))
|
||||
|
||||
return fos.set('firewall',
|
||||
'ipv6-eh-filter',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ipv6_eh_filter']:
|
||||
resp = firewall_ipv6_eh_filter(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"firewall_ipv6_eh_filter": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"auth": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dest_opt": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"fragment": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"hdopt_type": {"required": False, "type": "int"},
|
||||
"hop_opt": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"no_next": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"routing": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"routing_type": {"required": False, "type": "int"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,388 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ldb_monitor
|
||||
short_description: Configure server load balancing health monitors in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ldb_monitor category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ldb_monitor:
|
||||
description:
|
||||
- Configure server load balancing health monitors.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
http_get:
|
||||
description:
|
||||
- URL used to send a GET request to check the health of an HTTP server.
|
||||
type: str
|
||||
http_match:
|
||||
description:
|
||||
- String to match the value expected in response to an HTTP-GET request.
|
||||
type: str
|
||||
http_max_redirects:
|
||||
description:
|
||||
- The maximum number of HTTP redirects to be allowed (0 - 5).
|
||||
type: int
|
||||
interval:
|
||||
description:
|
||||
- Time between health checks (5 - 65635 sec).
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Monitor name.
|
||||
required: true
|
||||
type: str
|
||||
port:
|
||||
description:
|
||||
- Service port used to perform the health check. If 0, health check monitor inherits port configured for the server (0 - 65635).
|
||||
type: int
|
||||
retry:
|
||||
description:
|
||||
- Number health check attempts before the server is considered down (1 - 255).
|
||||
type: int
|
||||
timeout:
|
||||
description:
|
||||
- Time to wait to receive response to a health check from a server. Reaching the timeout means the health check failed (1 - 255 sec).
|
||||
type: int
|
||||
type:
|
||||
description:
|
||||
- Select the Monitor type used by the health check monitor to check the health of the server (PING | TCP | HTTP).
|
||||
type: str
|
||||
choices:
|
||||
- ping
|
||||
- tcp
|
||||
- http
|
||||
- passive-sip
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure server load balancing health monitors.
|
||||
fortios_firewall_ldb_monitor:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ldb_monitor:
|
||||
http_get: "<your_own_value>"
|
||||
http_match: "<your_own_value>"
|
||||
http_max_redirects: "5"
|
||||
interval: "6"
|
||||
name: "default_name_7"
|
||||
port: "8"
|
||||
retry: "9"
|
||||
timeout: "10"
|
||||
type: "ping"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ldb_monitor_data(json):
|
||||
option_list = ['http_get', 'http_match', 'http_max_redirects',
|
||||
'interval', 'name', 'port',
|
||||
'retry', 'timeout', 'type']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ldb_monitor(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ldb_monitor'] and data['firewall_ldb_monitor']:
|
||||
state = data['firewall_ldb_monitor']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ldb_monitor_data = data['firewall_ldb_monitor']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ldb_monitor_data(firewall_ldb_monitor_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'ldb-monitor',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'ldb-monitor',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ldb_monitor']:
|
||||
resp = firewall_ldb_monitor(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ldb_monitor": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"http_get": {"required": False, "type": "str"},
|
||||
"http_match": {"required": False, "type": "str"},
|
||||
"http_max_redirects": {"required": False, "type": "int"},
|
||||
"interval": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"port": {"required": False, "type": "int"},
|
||||
"retry": {"required": False, "type": "int"},
|
||||
"timeout": {"required": False, "type": "int"},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["ping", "tcp", "http",
|
||||
"passive-sip"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,434 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_local_in_policy
|
||||
short_description: Configure user defined IPv4 local-in policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and local_in_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_local_in_policy:
|
||||
description:
|
||||
- Configure user defined IPv4 local-in policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Action performed on traffic matching the policy .
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
ha_mgmt_intf_only:
|
||||
description:
|
||||
- Enable/disable dedicating the HA management interface only for local-in policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
intf:
|
||||
description:
|
||||
- Incoming interface name from available options. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
policyid:
|
||||
description:
|
||||
- User defined local in policy ID.
|
||||
required: true
|
||||
type: int
|
||||
schedule:
|
||||
description:
|
||||
- Schedule object from available options. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group
|
||||
.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Service object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this local-in policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure user defined IPv4 local-in policies.
|
||||
fortios_firewall_local_in_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_local_in_policy:
|
||||
action: "accept"
|
||||
comments: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_6 (source firewall.address.name firewall.addrgrp.name)"
|
||||
ha_mgmt_intf_only: "enable"
|
||||
intf: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
policyid: "9"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_12 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_14 (source firewall.address.name firewall.addrgrp.name)"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_local_in_policy_data(json):
|
||||
option_list = ['action', 'comments', 'dstaddr',
|
||||
'ha_mgmt_intf_only', 'intf', 'policyid',
|
||||
'schedule', 'service', 'srcaddr',
|
||||
'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_local_in_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_local_in_policy'] and data['firewall_local_in_policy']:
|
||||
state = data['firewall_local_in_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_local_in_policy_data = data['firewall_local_in_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_local_in_policy_data(firewall_local_in_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'local-in-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'local-in-policy',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_local_in_policy']:
|
||||
resp = firewall_local_in_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_local_in_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"ha_mgmt_intf_only": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"intf": {"required": False, "type": "str"},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,423 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_local_in_policy6
|
||||
short_description: Configure user defined IPv6 local-in policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and local_in_policy6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_local_in_policy6:
|
||||
description:
|
||||
- Configure user defined IPv6 local-in policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Action performed on traffic matching the policy .
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
intf:
|
||||
description:
|
||||
- Incoming interface name from available options. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
policyid:
|
||||
description:
|
||||
- User defined local in policy ID.
|
||||
required: true
|
||||
type: int
|
||||
schedule:
|
||||
description:
|
||||
- Schedule object from available options. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group
|
||||
.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Service object from available options. Separate names with a space.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address object from available options.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this local-in policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure user defined IPv6 local-in policies.
|
||||
fortios_firewall_local_in_policy6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_local_in_policy6:
|
||||
action: "accept"
|
||||
comments: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_6 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
intf: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
policyid: "8"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_11 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_13 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_local_in_policy6_data(json):
|
||||
option_list = ['action', 'comments', 'dstaddr',
|
||||
'intf', 'policyid', 'schedule',
|
||||
'service', 'srcaddr', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_local_in_policy6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_local_in_policy6'] and data['firewall_local_in_policy6']:
|
||||
state = data['firewall_local_in_policy6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_local_in_policy6_data = data['firewall_local_in_policy6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_local_in_policy6_data(firewall_local_in_policy6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'local-in-policy6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'local-in-policy6',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_local_in_policy6']:
|
||||
resp = firewall_local_in_policy6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_local_in_policy6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"intf": {"required": False, "type": "str"},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,431 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_multicast_address
|
||||
short_description: Configure multicast addresses in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and multicast_address category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_multicast_address:
|
||||
description:
|
||||
- Configure multicast addresses.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
associated_interface:
|
||||
description:
|
||||
- Interface associated with the address object. When setting up a policy, only addresses associated with this interface are available.
|
||||
Source system.interface.name.
|
||||
type: str
|
||||
color:
|
||||
description:
|
||||
- Integer value to determine the color of the icon in the GUI (1 - 32).
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
end_ip:
|
||||
description:
|
||||
- Final IPv4 address (inclusive) in the range for the address.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Multicast address name.
|
||||
required: true
|
||||
type: str
|
||||
start_ip:
|
||||
description:
|
||||
- First IPv4 address (inclusive) in the range for the address.
|
||||
type: str
|
||||
subnet:
|
||||
description:
|
||||
- Broadcast address and subnet.
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- "Type of address object: multicast IP address range or broadcast IP/mask to be treated as a multicast address."
|
||||
type: str
|
||||
choices:
|
||||
- multicastrange
|
||||
- broadcastmask
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable visibility of the multicast address on the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure multicast addresses.
|
||||
fortios_firewall_multicast_address:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_multicast_address:
|
||||
associated_interface: "<your_own_value> (source system.interface.name)"
|
||||
color: "4"
|
||||
comment: "Comment."
|
||||
end_ip: "<your_own_value>"
|
||||
name: "default_name_7"
|
||||
start_ip: "<your_own_value>"
|
||||
subnet: "<your_own_value>"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_12"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_14 (source system.object-tagging.tags.name)"
|
||||
type: "multicastrange"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_multicast_address_data(json):
|
||||
option_list = ['associated_interface', 'color', 'comment',
|
||||
'end_ip', 'name', 'start_ip',
|
||||
'subnet', 'tagging', 'type',
|
||||
'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_multicast_address(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_multicast_address'] and data['firewall_multicast_address']:
|
||||
state = data['firewall_multicast_address']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_multicast_address_data = data['firewall_multicast_address']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_multicast_address_data(firewall_multicast_address_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'multicast-address',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'multicast-address',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_multicast_address']:
|
||||
resp = firewall_multicast_address(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_multicast_address": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"associated_interface": {"required": False, "type": "str"},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"end_ip": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"start_ip": {"required": False, "type": "str"},
|
||||
"subnet": {"required": False, "type": "str"},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["multicastrange", "broadcastmask"]},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,400 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_multicast_address6
|
||||
short_description: Configure IPv6 multicast address in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and multicast_address6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_multicast_address6:
|
||||
description:
|
||||
- Configure IPv6 multicast address.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
ip6:
|
||||
description:
|
||||
- "IPv6 address prefix (format: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx/xxx)."
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- IPv6 multicast address name.
|
||||
required: true
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable visibility of the IPv6 multicast address on the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 multicast address.
|
||||
fortios_firewall_multicast_address6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_multicast_address6:
|
||||
color: "3"
|
||||
comment: "Comment."
|
||||
ip6: "<your_own_value>"
|
||||
name: "default_name_6"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_9"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_11 (source system.object-tagging.tags.name)"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_multicast_address6_data(json):
|
||||
option_list = ['color', 'comment', 'ip6',
|
||||
'name', 'tagging', 'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_multicast_address6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_multicast_address6'] and data['firewall_multicast_address6']:
|
||||
state = data['firewall_multicast_address6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_multicast_address6_data = data['firewall_multicast_address6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_multicast_address6_data(firewall_multicast_address6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'multicast-address6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'multicast-address6',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_multicast_address6']:
|
||||
resp = firewall_multicast_address6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_multicast_address6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"ip6": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,451 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_multicast_policy
|
||||
short_description: Configure multicast NAT policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and multicast_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_multicast_policy:
|
||||
description:
|
||||
- Configure multicast NAT policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Accept or deny traffic matching the policy.
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
dnat:
|
||||
description:
|
||||
- IPv4 DNAT address used for multicast destination addresses.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Destination address objects. Source firewall.multicast-address.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- Destination interface name. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
end_port:
|
||||
description:
|
||||
- Integer value for ending TCP/UDP/SCTP destination port in range (1 - 65535).
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
logtraffic:
|
||||
description:
|
||||
- Enable/disable logging traffic accepted by this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type as defined by IANA (0 - 255).
|
||||
type: int
|
||||
snat:
|
||||
description:
|
||||
- Enable/disable substitution of the outgoing interface IP address for the original source IP address (called source NAT or SNAT).
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
snat_ip:
|
||||
description:
|
||||
- IPv4 address to be used as the source address for NATed traffic.
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Source address objects. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
srcintf:
|
||||
description:
|
||||
- Source interface name. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
start_port:
|
||||
description:
|
||||
- Integer value for starting TCP/UDP/SCTP destination port in range (1 - 65535).
|
||||
type: int
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure multicast NAT policies.
|
||||
fortios_firewall_multicast_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_multicast_policy:
|
||||
action: "accept"
|
||||
dnat: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_6 (source firewall.multicast-address.name)"
|
||||
dstintf: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
end_port: "8"
|
||||
id: "9"
|
||||
logtraffic: "enable"
|
||||
protocol: "11"
|
||||
snat: "enable"
|
||||
snat_ip: "<your_own_value>"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_15 (source firewall.address.name firewall.addrgrp.name)"
|
||||
srcintf: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
start_port: "17"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_multicast_policy_data(json):
|
||||
option_list = ['action', 'dnat', 'dstaddr',
|
||||
'dstintf', 'end_port', 'id',
|
||||
'logtraffic', 'protocol', 'snat',
|
||||
'snat_ip', 'srcaddr', 'srcintf',
|
||||
'start_port', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_multicast_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_multicast_policy'] and data['firewall_multicast_policy']:
|
||||
state = data['firewall_multicast_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_multicast_policy_data = data['firewall_multicast_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_multicast_policy_data(firewall_multicast_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'multicast-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'multicast-policy',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_multicast_policy']:
|
||||
resp = firewall_multicast_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_multicast_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"dnat": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "str"},
|
||||
"end_port": {"required": False, "type": "int"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"protocol": {"required": False, "type": "int"},
|
||||
"snat": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"snat_ip": {"required": False, "type": "str"},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcintf": {"required": False, "type": "str"},
|
||||
"start_port": {"required": False, "type": "int"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,428 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_multicast_policy6
|
||||
short_description: Configure IPv6 multicast NAT policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and multicast_policy6 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_multicast_policy6:
|
||||
description:
|
||||
- Configure IPv6 multicast NAT policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Accept or deny traffic matching the policy.
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
dstaddr:
|
||||
description:
|
||||
- IPv6 destination address name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.multicast-address6.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- IPv6 destination interface name. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
end_port:
|
||||
description:
|
||||
- Integer value for ending TCP/UDP/SCTP destination port in range (1 - 65535).
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
logtraffic:
|
||||
description:
|
||||
- Enable/disable logging traffic accepted by this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type as defined by IANA (0 - 255).
|
||||
type: int
|
||||
srcaddr:
|
||||
description:
|
||||
- IPv6 source address name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
srcintf:
|
||||
description:
|
||||
- IPv6 source interface name. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
start_port:
|
||||
description:
|
||||
- Integer value for starting TCP/UDP/SCTP destination port in range (1 - 65535).
|
||||
type: int
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 multicast NAT policies.
|
||||
fortios_firewall_multicast_policy6:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_multicast_policy6:
|
||||
action: "accept"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_5 (source firewall.multicast-address6.name)"
|
||||
dstintf: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
end_port: "7"
|
||||
id: "8"
|
||||
logtraffic: "enable"
|
||||
protocol: "10"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_12 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
srcintf: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
start_port: "14"
|
||||
status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_multicast_policy6_data(json):
|
||||
option_list = ['action', 'dstaddr', 'dstintf',
|
||||
'end_port', 'id', 'logtraffic',
|
||||
'protocol', 'srcaddr', 'srcintf',
|
||||
'start_port', 'status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_multicast_policy6(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_multicast_policy6'] and data['firewall_multicast_policy6']:
|
||||
state = data['firewall_multicast_policy6']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_multicast_policy6_data = data['firewall_multicast_policy6']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_multicast_policy6_data(firewall_multicast_policy6_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'multicast-policy6',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'multicast-policy6',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_multicast_policy6']:
|
||||
resp = firewall_multicast_policy6(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_multicast_policy6": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "str"},
|
||||
"end_port": {"required": False, "type": "int"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"protocol": {"required": False, "type": "int"},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcintf": {"required": False, "type": "str"},
|
||||
"start_port": {"required": False, "type": "int"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,525 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_policy46
|
||||
short_description: Configure IPv4 to IPv6 policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and policy46 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_policy46:
|
||||
description:
|
||||
- Configure IPv4 to IPv6 policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Accept or deny traffic matching the policy.
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.vip46.name firewall.vipgrp46.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- Destination interface name. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
fixedport:
|
||||
description:
|
||||
- Enable/disable fixed port for this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ippool:
|
||||
description:
|
||||
- Enable/disable use of IP Pools for source NAT.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
logtraffic:
|
||||
description:
|
||||
- Enable/disable traffic logging for this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
per_ip_shaper:
|
||||
description:
|
||||
- Per IP traffic shaper. Source firewall.shaper.per-ip-shaper.name.
|
||||
type: str
|
||||
permit_any_host:
|
||||
description:
|
||||
- Enable/disable allowing any host.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
poolname:
|
||||
description:
|
||||
- IP Pool names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- IP pool name. Source firewall.ippool6.name.
|
||||
required: true
|
||||
type: str
|
||||
schedule:
|
||||
description:
|
||||
- Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Service name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
srcintf:
|
||||
description:
|
||||
- Source interface name. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
tcp_mss_receiver:
|
||||
description:
|
||||
- TCP Maximum Segment Size value of receiver (0 - 65535)
|
||||
type: int
|
||||
tcp_mss_sender:
|
||||
description:
|
||||
- TCP Maximum Segment Size value of sender (0 - 65535).
|
||||
type: int
|
||||
traffic_shaper:
|
||||
description:
|
||||
- Traffic shaper. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
traffic_shaper_reverse:
|
||||
description:
|
||||
- Reverse traffic shaper. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv4 to IPv6 policies.
|
||||
fortios_firewall_policy46:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_policy46:
|
||||
action: "accept"
|
||||
comments: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_6 (source firewall.vip46.name firewall.vipgrp46.name)"
|
||||
dstintf: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
fixedport: "enable"
|
||||
ippool: "enable"
|
||||
logtraffic: "enable"
|
||||
per_ip_shaper: "<your_own_value> (source firewall.shaper.per-ip-shaper.name)"
|
||||
permit_any_host: "enable"
|
||||
policyid: "13"
|
||||
poolname:
|
||||
-
|
||||
name: "default_name_15 (source firewall.ippool6.name)"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_18 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_20 (source firewall.address.name firewall.addrgrp.name)"
|
||||
srcintf: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
status: "enable"
|
||||
tcp_mss_receiver: "23"
|
||||
tcp_mss_sender: "24"
|
||||
traffic_shaper: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
traffic_shaper_reverse: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
uuid: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_policy46_data(json):
|
||||
option_list = ['action', 'comments', 'dstaddr',
|
||||
'dstintf', 'fixedport', 'ippool',
|
||||
'logtraffic', 'per_ip_shaper', 'permit_any_host',
|
||||
'policyid', 'poolname', 'schedule',
|
||||
'service', 'srcaddr', 'srcintf',
|
||||
'status', 'tcp_mss_receiver', 'tcp_mss_sender',
|
||||
'traffic_shaper', 'traffic_shaper_reverse', 'uuid']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_policy46(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_policy46'] and data['firewall_policy46']:
|
||||
state = data['firewall_policy46']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_policy46_data = data['firewall_policy46']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_policy46_data(firewall_policy46_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'policy46',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'policy46',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_policy46']:
|
||||
resp = firewall_policy46(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_policy46": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "str"},
|
||||
"fixedport": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ippool": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"per_ip_shaper": {"required": False, "type": "str"},
|
||||
"permit_any_host": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"poolname": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcintf": {"required": False, "type": "str"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"tcp_mss_receiver": {"required": False, "type": "int"},
|
||||
"tcp_mss_sender": {"required": False, "type": "int"},
|
||||
"traffic_shaper": {"required": False, "type": "str"},
|
||||
"traffic_shaper_reverse": {"required": False, "type": "str"},
|
||||
"uuid": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,525 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_policy64
|
||||
short_description: Configure IPv6 to IPv4 policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and policy64 category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_policy64:
|
||||
description:
|
||||
- Configure IPv6 to IPv4 policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Policy action.
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
comments:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.vip64.name firewall.vipgrp64.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- Destination interface name. Source system.interface.name system.zone.name.
|
||||
type: str
|
||||
fixedport:
|
||||
description:
|
||||
- Enable/disable policy fixed port.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ippool:
|
||||
description:
|
||||
- Enable/disable policy64 IP pool.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
logtraffic:
|
||||
description:
|
||||
- Enable/disable policy log traffic.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
per_ip_shaper:
|
||||
description:
|
||||
- Per-IP traffic shaper. Source firewall.shaper.per-ip-shaper.name.
|
||||
type: str
|
||||
permit_any_host:
|
||||
description:
|
||||
- Enable/disable permit any host in.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
poolname:
|
||||
description:
|
||||
- Policy IP pool names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- IP pool name. Source firewall.ippool.name.
|
||||
required: true
|
||||
type: str
|
||||
schedule:
|
||||
description:
|
||||
- Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Service name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
srcintf:
|
||||
description:
|
||||
- Source interface name. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable policy status.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
tcp_mss_receiver:
|
||||
description:
|
||||
- TCP MSS value of receiver.
|
||||
type: int
|
||||
tcp_mss_sender:
|
||||
description:
|
||||
- TCP MSS value of sender.
|
||||
type: int
|
||||
traffic_shaper:
|
||||
description:
|
||||
- Traffic shaper. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
traffic_shaper_reverse:
|
||||
description:
|
||||
- Reverse traffic shaper. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure IPv6 to IPv4 policies.
|
||||
fortios_firewall_policy64:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_policy64:
|
||||
action: "accept"
|
||||
comments: "<your_own_value>"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_6 (source firewall.address.name firewall.addrgrp.name firewall.vip64.name firewall.vipgrp64.name)"
|
||||
dstintf: "<your_own_value> (source system.interface.name system.zone.name)"
|
||||
fixedport: "enable"
|
||||
ippool: "enable"
|
||||
logtraffic: "enable"
|
||||
per_ip_shaper: "<your_own_value> (source firewall.shaper.per-ip-shaper.name)"
|
||||
permit_any_host: "enable"
|
||||
policyid: "13"
|
||||
poolname:
|
||||
-
|
||||
name: "default_name_15 (source firewall.ippool.name)"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_18 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_20 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
srcintf: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
status: "enable"
|
||||
tcp_mss_receiver: "23"
|
||||
tcp_mss_sender: "24"
|
||||
traffic_shaper: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
traffic_shaper_reverse: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
uuid: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_policy64_data(json):
|
||||
option_list = ['action', 'comments', 'dstaddr',
|
||||
'dstintf', 'fixedport', 'ippool',
|
||||
'logtraffic', 'per_ip_shaper', 'permit_any_host',
|
||||
'policyid', 'poolname', 'schedule',
|
||||
'service', 'srcaddr', 'srcintf',
|
||||
'status', 'tcp_mss_receiver', 'tcp_mss_sender',
|
||||
'traffic_shaper', 'traffic_shaper_reverse', 'uuid']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_policy64(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_policy64'] and data['firewall_policy64']:
|
||||
state = data['firewall_policy64']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_policy64_data = data['firewall_policy64']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_policy64_data(firewall_policy64_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'policy64',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'policy64',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_policy64']:
|
||||
resp = firewall_policy64(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_policy64": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "str"},
|
||||
"fixedport": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ippool": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"per_ip_shaper": {"required": False, "type": "str"},
|
||||
"permit_any_host": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"poolname": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcintf": {"required": False, "type": "str"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"tcp_mss_receiver": {"required": False, "type": "int"},
|
||||
"tcp_mss_sender": {"required": False, "type": "int"},
|
||||
"traffic_shaper": {"required": False, "type": "str"},
|
||||
"traffic_shaper_reverse": {"required": False, "type": "str"},
|
||||
"uuid": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,413 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_profile_group
|
||||
short_description: Configure profile groups in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and profile_group category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_profile_group:
|
||||
description:
|
||||
- Configure profile groups.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
application_list:
|
||||
description:
|
||||
- Name of an existing Application list. Source application.list.name.
|
||||
type: str
|
||||
av_profile:
|
||||
description:
|
||||
- Name of an existing Antivirus profile. Source antivirus.profile.name.
|
||||
type: str
|
||||
dlp_sensor:
|
||||
description:
|
||||
- Name of an existing DLP sensor. Source dlp.sensor.name.
|
||||
type: str
|
||||
dnsfilter_profile:
|
||||
description:
|
||||
- Name of an existing DNS filter profile. Source dnsfilter.profile.name.
|
||||
type: str
|
||||
icap_profile:
|
||||
description:
|
||||
- Name of an existing ICAP profile. Source icap.profile.name.
|
||||
type: str
|
||||
ips_sensor:
|
||||
description:
|
||||
- Name of an existing IPS sensor. Source ips.sensor.name.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Profile group name.
|
||||
required: true
|
||||
type: str
|
||||
profile_protocol_options:
|
||||
description:
|
||||
- Name of an existing Protocol options profile. Source firewall.profile-protocol-options.name.
|
||||
type: str
|
||||
spamfilter_profile:
|
||||
description:
|
||||
- Name of an existing Spam filter profile. Source spamfilter.profile.name.
|
||||
type: str
|
||||
ssh_filter_profile:
|
||||
description:
|
||||
- Name of an existing SSH filter profile. Source ssh-filter.profile.name.
|
||||
type: str
|
||||
ssl_ssh_profile:
|
||||
description:
|
||||
- Name of an existing SSL SSH profile. Source firewall.ssl-ssh-profile.name.
|
||||
type: str
|
||||
voip_profile:
|
||||
description:
|
||||
- Name of an existing VoIP profile. Source voip.profile.name.
|
||||
type: str
|
||||
waf_profile:
|
||||
description:
|
||||
- Name of an existing Web application firewall profile. Source waf.profile.name.
|
||||
type: str
|
||||
webfilter_profile:
|
||||
description:
|
||||
- Name of an existing Web filter profile. Source webfilter.profile.name.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure profile groups.
|
||||
fortios_firewall_profile_group:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_profile_group:
|
||||
application_list: "<your_own_value> (source application.list.name)"
|
||||
av_profile: "<your_own_value> (source antivirus.profile.name)"
|
||||
dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
|
||||
dnsfilter_profile: "<your_own_value> (source dnsfilter.profile.name)"
|
||||
icap_profile: "<your_own_value> (source icap.profile.name)"
|
||||
ips_sensor: "<your_own_value> (source ips.sensor.name)"
|
||||
name: "default_name_9"
|
||||
profile_protocol_options: "<your_own_value> (source firewall.profile-protocol-options.name)"
|
||||
spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
|
||||
ssh_filter_profile: "<your_own_value> (source ssh-filter.profile.name)"
|
||||
ssl_ssh_profile: "<your_own_value> (source firewall.ssl-ssh-profile.name)"
|
||||
voip_profile: "<your_own_value> (source voip.profile.name)"
|
||||
waf_profile: "<your_own_value> (source waf.profile.name)"
|
||||
webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_profile_group_data(json):
|
||||
option_list = ['application_list', 'av_profile', 'dlp_sensor',
|
||||
'dnsfilter_profile', 'icap_profile', 'ips_sensor',
|
||||
'name', 'profile_protocol_options', 'spamfilter_profile',
|
||||
'ssh_filter_profile', 'ssl_ssh_profile', 'voip_profile',
|
||||
'waf_profile', 'webfilter_profile']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_profile_group(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_profile_group'] and data['firewall_profile_group']:
|
||||
state = data['firewall_profile_group']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_profile_group_data = data['firewall_profile_group']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_profile_group_data(firewall_profile_group_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'profile-group',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'profile-group',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_profile_group']:
|
||||
resp = firewall_profile_group(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_profile_group": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"application_list": {"required": False, "type": "str"},
|
||||
"av_profile": {"required": False, "type": "str"},
|
||||
"dlp_sensor": {"required": False, "type": "str"},
|
||||
"dnsfilter_profile": {"required": False, "type": "str"},
|
||||
"icap_profile": {"required": False, "type": "str"},
|
||||
"ips_sensor": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"profile_protocol_options": {"required": False, "type": "str"},
|
||||
"spamfilter_profile": {"required": False, "type": "str"},
|
||||
"ssh_filter_profile": {"required": False, "type": "str"},
|
||||
"ssl_ssh_profile": {"required": False, "type": "str"},
|
||||
"voip_profile": {"required": False, "type": "str"},
|
||||
"waf_profile": {"required": False, "type": "str"},
|
||||
"webfilter_profile": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,567 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_proxy_address
|
||||
short_description: Web proxy address configuration in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and proxy_address category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_proxy_address:
|
||||
description:
|
||||
- Web proxy address configuration.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
case_sensitivity:
|
||||
description:
|
||||
- Enable to make the pattern case sensitive.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
category:
|
||||
description:
|
||||
- FortiGuard category ID.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Fortiguard category id.
|
||||
required: true
|
||||
type: int
|
||||
color:
|
||||
description:
|
||||
- Integer value to determine the color of the icon in the GUI (1 - 32).
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Optional comments.
|
||||
type: str
|
||||
header:
|
||||
description:
|
||||
- HTTP header name as a regular expression.
|
||||
type: str
|
||||
header_group:
|
||||
description:
|
||||
- HTTP header group.
|
||||
type: list
|
||||
suboptions:
|
||||
case_sensitivity:
|
||||
description:
|
||||
- Case sensitivity in pattern.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
header:
|
||||
description:
|
||||
- HTTP header regular expression.
|
||||
type: str
|
||||
header_name:
|
||||
description:
|
||||
- HTTP header.
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
header_name:
|
||||
description:
|
||||
- Name of HTTP header.
|
||||
type: str
|
||||
host:
|
||||
description:
|
||||
- Address object for the host. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name.
|
||||
type: str
|
||||
host_regex:
|
||||
description:
|
||||
- Host name as a regular expression.
|
||||
type: str
|
||||
method:
|
||||
description:
|
||||
- HTTP request methods to be used.
|
||||
type: str
|
||||
choices:
|
||||
- get
|
||||
- post
|
||||
- put
|
||||
- head
|
||||
- connect
|
||||
- trace
|
||||
- options
|
||||
- delete
|
||||
name:
|
||||
description:
|
||||
- Address name.
|
||||
required: true
|
||||
type: str
|
||||
path:
|
||||
description:
|
||||
- URL path as a regular expression.
|
||||
type: str
|
||||
query:
|
||||
description:
|
||||
- Match the query part of the URL as a regular expression.
|
||||
type: str
|
||||
referrer:
|
||||
description:
|
||||
- Enable/disable use of referrer field in the HTTP header to match the address.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Proxy address type.
|
||||
type: str
|
||||
choices:
|
||||
- host-regex
|
||||
- url
|
||||
- category
|
||||
- method
|
||||
- ua
|
||||
- header
|
||||
- src-advanced
|
||||
- dst-advanced
|
||||
ua:
|
||||
description:
|
||||
- Names of browsers to be used as user agent.
|
||||
type: str
|
||||
choices:
|
||||
- chrome
|
||||
- ms
|
||||
- firefox
|
||||
- safari
|
||||
- other
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable visibility of the object in the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Web proxy address configuration.
|
||||
fortios_firewall_proxy_address:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_proxy_address:
|
||||
case_sensitivity: "disable"
|
||||
category:
|
||||
-
|
||||
id: "5"
|
||||
color: "6"
|
||||
comment: "Optional comments."
|
||||
header: "<your_own_value>"
|
||||
header_group:
|
||||
-
|
||||
case_sensitivity: "disable"
|
||||
header: "<your_own_value>"
|
||||
header_name: "<your_own_value>"
|
||||
id: "13"
|
||||
header_name: "<your_own_value>"
|
||||
host: "myhostname (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name)"
|
||||
host_regex: "myhostname"
|
||||
method: "get"
|
||||
name: "default_name_18"
|
||||
path: "<your_own_value>"
|
||||
query: "<your_own_value>"
|
||||
referrer: "enable"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_24"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_26 (source system.object-tagging.tags.name)"
|
||||
type: "host-regex"
|
||||
ua: "chrome"
|
||||
uuid: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_proxy_address_data(json):
|
||||
option_list = ['case_sensitivity', 'category', 'color',
|
||||
'comment', 'header', 'header_group',
|
||||
'header_name', 'host', 'host_regex',
|
||||
'method', 'name', 'path',
|
||||
'query', 'referrer', 'tagging',
|
||||
'type', 'ua', 'uuid',
|
||||
'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_proxy_address(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_proxy_address'] and data['firewall_proxy_address']:
|
||||
state = data['firewall_proxy_address']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_proxy_address_data = data['firewall_proxy_address']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_proxy_address_data(firewall_proxy_address_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'proxy-address',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'proxy-address',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_proxy_address']:
|
||||
resp = firewall_proxy_address(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_proxy_address": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"case_sensitivity": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"header": {"required": False, "type": "str"},
|
||||
"header_group": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"case_sensitivity": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"header": {"required": False, "type": "str"},
|
||||
"header_name": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"header_name": {"required": False, "type": "str"},
|
||||
"host": {"required": False, "type": "str"},
|
||||
"host_regex": {"required": False, "type": "str"},
|
||||
"method": {"required": False, "type": "str",
|
||||
"choices": ["get", "post", "put",
|
||||
"head", "connect", "trace",
|
||||
"options", "delete"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"path": {"required": False, "type": "str"},
|
||||
"query": {"required": False, "type": "str"},
|
||||
"referrer": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["host-regex", "url", "category",
|
||||
"method", "ua", "header",
|
||||
"src-advanced", "dst-advanced"]},
|
||||
"ua": {"required": False, "type": "str",
|
||||
"choices": ["chrome", "ms", "firefox",
|
||||
"safari", "other"]},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,428 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_proxy_addrgrp
|
||||
short_description: Web proxy address group configuration in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and proxy_addrgrp category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_proxy_addrgrp:
|
||||
description:
|
||||
- Web proxy address group configuration.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Integer value to determine the color of the icon in the GUI (1 - 32).
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Optional comments.
|
||||
type: str
|
||||
member:
|
||||
description:
|
||||
- Members of address group.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.proxy-address.name firewall.proxy-addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Address group name.
|
||||
required: true
|
||||
type: str
|
||||
tagging:
|
||||
description:
|
||||
- Config object tagging.
|
||||
type: list
|
||||
suboptions:
|
||||
category:
|
||||
description:
|
||||
- Tag category. Source system.object-tagging.category.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Tagging entry name.
|
||||
required: true
|
||||
type: str
|
||||
tags:
|
||||
description:
|
||||
- Tags.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Tag name. Source system.object-tagging.tags.name.
|
||||
required: true
|
||||
type: str
|
||||
type:
|
||||
description:
|
||||
- Source or destination address group type.
|
||||
type: str
|
||||
choices:
|
||||
- src
|
||||
- dst
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable visibility of the object in the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Web proxy address group configuration.
|
||||
fortios_firewall_proxy_addrgrp:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_proxy_addrgrp:
|
||||
color: "3"
|
||||
comment: "Optional comments."
|
||||
member:
|
||||
-
|
||||
name: "default_name_6 (source firewall.proxy-address.name firewall.proxy-addrgrp.name)"
|
||||
name: "default_name_7"
|
||||
tagging:
|
||||
-
|
||||
category: "<your_own_value> (source system.object-tagging.category)"
|
||||
name: "default_name_10"
|
||||
tags:
|
||||
-
|
||||
name: "default_name_12 (source system.object-tagging.tags.name)"
|
||||
type: "src"
|
||||
uuid: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_proxy_addrgrp_data(json):
|
||||
option_list = ['color', 'comment', 'member',
|
||||
'name', 'tagging', 'type',
|
||||
'uuid', 'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_proxy_addrgrp(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_proxy_addrgrp'] and data['firewall_proxy_addrgrp']:
|
||||
state = data['firewall_proxy_addrgrp']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_proxy_addrgrp_data = data['firewall_proxy_addrgrp']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_proxy_addrgrp_data(firewall_proxy_addrgrp_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'proxy-addrgrp',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'proxy-addrgrp',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_proxy_addrgrp']:
|
||||
resp = firewall_proxy_addrgrp(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_proxy_addrgrp": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"member": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tagging": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"category": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"tags": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
}},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["src", "dst"]},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,881 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_proxy_policy
|
||||
short_description: Configure proxy policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and proxy_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_proxy_policy:
|
||||
description:
|
||||
- Configure proxy policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Accept or deny traffic matching the policy parameters.
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
- redirect
|
||||
application_list:
|
||||
description:
|
||||
- Name of an existing Application list. Source application.list.name.
|
||||
type: str
|
||||
av_profile:
|
||||
description:
|
||||
- Name of an existing Antivirus profile. Source antivirus.profile.name.
|
||||
type: str
|
||||
comments:
|
||||
description:
|
||||
- Optional comments.
|
||||
type: str
|
||||
disclaimer:
|
||||
description:
|
||||
- "Web proxy disclaimer setting: by domain, policy, or user."
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- domain
|
||||
- policy
|
||||
- user
|
||||
dlp_sensor:
|
||||
description:
|
||||
- Name of an existing DLP sensor. Source dlp.sensor.name.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- Destination address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name
|
||||
firewall.vip.name firewall.vipgrp.name firewall.vip46.name firewall.vipgrp46.name system.external-resource.name.
|
||||
required: true
|
||||
type: str
|
||||
dstaddr_negate:
|
||||
description:
|
||||
- When enabled, destination addresses match against any address EXCEPT the specified destination addresses.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dstaddr6:
|
||||
description:
|
||||
- IPv6 destination address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name firewall.vip6.name firewall.vipgrp6.name firewall.vip64.name
|
||||
firewall.vipgrp64.name system.external-resource.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- Destination interface names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Interface name. Source system.interface.name system.zone.name.
|
||||
required: true
|
||||
type: str
|
||||
global_label:
|
||||
description:
|
||||
- Global web-based manager visible label.
|
||||
type: str
|
||||
groups:
|
||||
description:
|
||||
- Names of group objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Group name. Source user.group.name.
|
||||
required: true
|
||||
type: str
|
||||
http_tunnel_auth:
|
||||
description:
|
||||
- Enable/disable HTTP tunnel authentication.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
icap_profile:
|
||||
description:
|
||||
- Name of an existing ICAP profile. Source icap.profile.name.
|
||||
type: str
|
||||
internet_service:
|
||||
description:
|
||||
- Enable/disable use of Internet Services for this policy. If enabled, destination address and service are not used.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
internet_service_custom:
|
||||
description:
|
||||
- Custom Internet Service name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Custom name. Source firewall.internet-service-custom.name.
|
||||
required: true
|
||||
type: str
|
||||
internet_service_id:
|
||||
description:
|
||||
- Internet Service ID.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Internet Service ID. Source firewall.internet-service.id.
|
||||
required: true
|
||||
type: int
|
||||
internet_service_negate:
|
||||
description:
|
||||
- When enabled, Internet Services match against any internet service EXCEPT the selected Internet Service.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ips_sensor:
|
||||
description:
|
||||
- Name of an existing IPS sensor. Source ips.sensor.name.
|
||||
type: str
|
||||
label:
|
||||
description:
|
||||
- VDOM-specific GUI visible label.
|
||||
type: str
|
||||
logtraffic:
|
||||
description:
|
||||
- Enable/disable logging traffic through the policy.
|
||||
type: str
|
||||
choices:
|
||||
- all
|
||||
- utm
|
||||
- disable
|
||||
logtraffic_start:
|
||||
description:
|
||||
- Enable/disable policy log traffic start.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
policyid:
|
||||
description:
|
||||
- Policy ID.
|
||||
required: true
|
||||
type: int
|
||||
poolname:
|
||||
description:
|
||||
- Name of IP pool object.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- IP pool name. Source firewall.ippool.name.
|
||||
required: true
|
||||
type: str
|
||||
profile_group:
|
||||
description:
|
||||
- Name of profile group. Source firewall.profile-group.name.
|
||||
type: str
|
||||
profile_protocol_options:
|
||||
description:
|
||||
- Name of an existing Protocol options profile. Source firewall.profile-protocol-options.name.
|
||||
type: str
|
||||
profile_type:
|
||||
description:
|
||||
- Determine whether the firewall policy allows security profile groups or single profiles only.
|
||||
type: str
|
||||
choices:
|
||||
- single
|
||||
- group
|
||||
proxy:
|
||||
description:
|
||||
- Type of explicit proxy.
|
||||
type: str
|
||||
choices:
|
||||
- explicit-web
|
||||
- transparent-web
|
||||
- ftp
|
||||
- ssh
|
||||
- ssh-tunnel
|
||||
- wanopt
|
||||
redirect_url:
|
||||
description:
|
||||
- Redirect URL for further explicit web proxy processing.
|
||||
type: str
|
||||
replacemsg_override_group:
|
||||
description:
|
||||
- Authentication replacement message override group. Source system.replacemsg-group.name.
|
||||
type: str
|
||||
scan_botnet_connections:
|
||||
description:
|
||||
- Enable/disable scanning of connections to Botnet servers.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- block
|
||||
- monitor
|
||||
schedule:
|
||||
description:
|
||||
- Name of schedule object. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Name of service objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
service_negate:
|
||||
description:
|
||||
- When enabled, services match against any service EXCEPT the specified destination services.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
session_ttl:
|
||||
description:
|
||||
- TTL in seconds for sessions accepted by this policy (0 means use the system ).
|
||||
type: int
|
||||
spamfilter_profile:
|
||||
description:
|
||||
- Name of an existing Spam filter profile. Source spamfilter.profile.name.
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name system
|
||||
.external-resource.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr_negate:
|
||||
description:
|
||||
- When enabled, source addresses match against any address EXCEPT the specified source addresses.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
srcaddr6:
|
||||
description:
|
||||
- IPv6 source address objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name system.external-resource.name.
|
||||
required: true
|
||||
type: str
|
||||
srcintf:
|
||||
description:
|
||||
- Source interface names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Interface name. Source system.interface.name system.zone.name.
|
||||
required: true
|
||||
type: str
|
||||
ssh_filter_profile:
|
||||
description:
|
||||
- Name of an existing SSH filter profile. Source ssh-filter.profile.name.
|
||||
type: str
|
||||
ssl_ssh_profile:
|
||||
description:
|
||||
- Name of an existing SSL SSH profile. Source firewall.ssl-ssh-profile.name.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable the active status of the policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
transparent:
|
||||
description:
|
||||
- Enable to use the IP address of the client to connect to the server.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
users:
|
||||
description:
|
||||
- Names of user objects.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Group name. Source user.local.name.
|
||||
required: true
|
||||
type: str
|
||||
utm_status:
|
||||
description:
|
||||
- Enable the use of UTM profiles/sensors/lists.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
uuid:
|
||||
description:
|
||||
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
|
||||
type: str
|
||||
waf_profile:
|
||||
description:
|
||||
- Name of an existing Web application firewall profile. Source waf.profile.name.
|
||||
type: str
|
||||
webcache:
|
||||
description:
|
||||
- Enable/disable web caching.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
webcache_https:
|
||||
description:
|
||||
- Enable/disable web caching for HTTPS (Requires deep-inspection enabled in ssl-ssh-profile).
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
webfilter_profile:
|
||||
description:
|
||||
- Name of an existing Web filter profile. Source webfilter.profile.name.
|
||||
type: str
|
||||
webproxy_forward_server:
|
||||
description:
|
||||
- Name of web proxy forward server. Source web-proxy.forward-server.name web-proxy.forward-server-group.name.
|
||||
type: str
|
||||
webproxy_profile:
|
||||
description:
|
||||
- Name of web proxy profile. Source web-proxy.profile.name.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure proxy policies.
|
||||
fortios_firewall_proxy_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_proxy_policy:
|
||||
action: "accept"
|
||||
application_list: "<your_own_value> (source application.list.name)"
|
||||
av_profile: "<your_own_value> (source antivirus.profile.name)"
|
||||
comments: "<your_own_value>"
|
||||
disclaimer: "disable"
|
||||
dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_10 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name firewall.vip
|
||||
.name firewall.vipgrp.name firewall.vip46.name firewall.vipgrp46.name system.external-resource.name)"
|
||||
dstaddr_negate: "enable"
|
||||
dstaddr6:
|
||||
-
|
||||
name: "default_name_13 (source firewall.address6.name firewall.addrgrp6.name firewall.vip6.name firewall.vipgrp6.name firewall.vip64.name firewall
|
||||
.vipgrp64.name system.external-resource.name)"
|
||||
dstintf:
|
||||
-
|
||||
name: "default_name_15 (source system.interface.name system.zone.name)"
|
||||
global_label: "<your_own_value>"
|
||||
groups:
|
||||
-
|
||||
name: "default_name_18 (source user.group.name)"
|
||||
http_tunnel_auth: "enable"
|
||||
icap_profile: "<your_own_value> (source icap.profile.name)"
|
||||
internet_service: "enable"
|
||||
internet_service_custom:
|
||||
-
|
||||
name: "default_name_23 (source firewall.internet-service-custom.name)"
|
||||
internet_service_id:
|
||||
-
|
||||
id: "25 (source firewall.internet-service.id)"
|
||||
internet_service_negate: "enable"
|
||||
ips_sensor: "<your_own_value> (source ips.sensor.name)"
|
||||
label: "<your_own_value>"
|
||||
logtraffic: "all"
|
||||
logtraffic_start: "enable"
|
||||
policyid: "31"
|
||||
poolname:
|
||||
-
|
||||
name: "default_name_33 (source firewall.ippool.name)"
|
||||
profile_group: "<your_own_value> (source firewall.profile-group.name)"
|
||||
profile_protocol_options: "<your_own_value> (source firewall.profile-protocol-options.name)"
|
||||
profile_type: "single"
|
||||
proxy: "explicit-web"
|
||||
redirect_url: "<your_own_value>"
|
||||
replacemsg_override_group: "<your_own_value> (source system.replacemsg-group.name)"
|
||||
scan_botnet_connections: "disable"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_43 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
service_negate: "enable"
|
||||
session_ttl: "45"
|
||||
spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_48 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name system
|
||||
.external-resource.name)"
|
||||
srcaddr_negate: "enable"
|
||||
srcaddr6:
|
||||
-
|
||||
name: "default_name_51 (source firewall.address6.name firewall.addrgrp6.name system.external-resource.name)"
|
||||
srcintf:
|
||||
-
|
||||
name: "default_name_53 (source system.interface.name system.zone.name)"
|
||||
ssh_filter_profile: "<your_own_value> (source ssh-filter.profile.name)"
|
||||
ssl_ssh_profile: "<your_own_value> (source firewall.ssl-ssh-profile.name)"
|
||||
status: "enable"
|
||||
transparent: "enable"
|
||||
users:
|
||||
-
|
||||
name: "default_name_59 (source user.local.name)"
|
||||
utm_status: "enable"
|
||||
uuid: "<your_own_value>"
|
||||
waf_profile: "<your_own_value> (source waf.profile.name)"
|
||||
webcache: "enable"
|
||||
webcache_https: "disable"
|
||||
webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
|
||||
webproxy_forward_server: "<your_own_value> (source web-proxy.forward-server.name web-proxy.forward-server-group.name)"
|
||||
webproxy_profile: "<your_own_value> (source web-proxy.profile.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_proxy_policy_data(json):
|
||||
option_list = ['action', 'application_list', 'av_profile',
|
||||
'comments', 'disclaimer', 'dlp_sensor',
|
||||
'dstaddr', 'dstaddr_negate', 'dstaddr6',
|
||||
'dstintf', 'global_label', 'groups',
|
||||
'http_tunnel_auth', 'icap_profile', 'internet_service',
|
||||
'internet_service_custom', 'internet_service_id', 'internet_service_negate',
|
||||
'ips_sensor', 'label', 'logtraffic',
|
||||
'logtraffic_start', 'policyid', 'poolname',
|
||||
'profile_group', 'profile_protocol_options', 'profile_type',
|
||||
'proxy', 'redirect_url', 'replacemsg_override_group',
|
||||
'scan_botnet_connections', 'schedule', 'service',
|
||||
'service_negate', 'session_ttl', 'spamfilter_profile',
|
||||
'srcaddr', 'srcaddr_negate', 'srcaddr6',
|
||||
'srcintf', 'ssh_filter_profile', 'ssl_ssh_profile',
|
||||
'status', 'transparent', 'users',
|
||||
'utm_status', 'uuid', 'waf_profile',
|
||||
'webcache', 'webcache_https', 'webfilter_profile',
|
||||
'webproxy_forward_server', 'webproxy_profile']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_proxy_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_proxy_policy'] and data['firewall_proxy_policy']:
|
||||
state = data['firewall_proxy_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_proxy_policy_data = data['firewall_proxy_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_proxy_policy_data(firewall_proxy_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'proxy-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'proxy-policy',
|
||||
mkey=filtered_data['policyid'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_proxy_policy']:
|
||||
resp = firewall_proxy_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_proxy_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny", "redirect"]},
|
||||
"application_list": {"required": False, "type": "str"},
|
||||
"av_profile": {"required": False, "type": "str"},
|
||||
"comments": {"required": False, "type": "str"},
|
||||
"disclaimer": {"required": False, "type": "str",
|
||||
"choices": ["disable", "domain", "policy",
|
||||
"user"]},
|
||||
"dlp_sensor": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstaddr_negate": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dstaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"global_label": {"required": False, "type": "str"},
|
||||
"groups": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"http_tunnel_auth": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"icap_profile": {"required": False, "type": "str"},
|
||||
"internet_service": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"internet_service_custom": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"internet_service_id": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"internet_service_negate": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ips_sensor": {"required": False, "type": "str"},
|
||||
"label": {"required": False, "type": "str"},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["all", "utm", "disable"]},
|
||||
"logtraffic_start": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"policyid": {"required": True, "type": "int"},
|
||||
"poolname": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"profile_group": {"required": False, "type": "str"},
|
||||
"profile_protocol_options": {"required": False, "type": "str"},
|
||||
"profile_type": {"required": False, "type": "str",
|
||||
"choices": ["single", "group"]},
|
||||
"proxy": {"required": False, "type": "str",
|
||||
"choices": ["explicit-web", "transparent-web", "ftp",
|
||||
"ssh", "ssh-tunnel", "wanopt"]},
|
||||
"redirect_url": {"required": False, "type": "str"},
|
||||
"replacemsg_override_group": {"required": False, "type": "str"},
|
||||
"scan_botnet_connections": {"required": False, "type": "str",
|
||||
"choices": ["disable", "block", "monitor"]},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"service_negate": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"session_ttl": {"required": False, "type": "int"},
|
||||
"spamfilter_profile": {"required": False, "type": "str"},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr_negate": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"srcaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcintf": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"ssh_filter_profile": {"required": False, "type": "str"},
|
||||
"ssl_ssh_profile": {"required": False, "type": "str"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"transparent": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"users": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"utm_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"uuid": {"required": False, "type": "str"},
|
||||
"waf_profile": {"required": False, "type": "str"},
|
||||
"webcache": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"webcache_https": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"webfilter_profile": {"required": False, "type": "str"},
|
||||
"webproxy_forward_server": {"required": False, "type": "str"},
|
||||
"webproxy_profile": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,354 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_schedule_group
|
||||
short_description: Schedule group configuration in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_schedule feature and group category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_schedule_group:
|
||||
description:
|
||||
- Schedule group configuration.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
member:
|
||||
description:
|
||||
- Schedules added to the schedule group.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Schedule group name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Schedule group configuration.
|
||||
fortios_firewall_schedule_group:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_schedule_group:
|
||||
color: "3"
|
||||
member:
|
||||
-
|
||||
name: "default_name_5 (source firewall.schedule.onetime.name firewall.schedule.recurring.name)"
|
||||
name: "default_name_6"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_schedule_group_data(json):
|
||||
option_list = ['color', 'member', 'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_schedule_group(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_schedule_group'] and data['firewall_schedule_group']:
|
||||
state = data['firewall_schedule_group']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_schedule_group_data = data['firewall_schedule_group']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_schedule_group_data(firewall_schedule_group_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.schedule',
|
||||
'group',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.schedule',
|
||||
'group',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_schedule(data, fos):
|
||||
|
||||
if data['firewall_schedule_group']:
|
||||
resp = firewall_schedule_group(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_schedule_group": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"member": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,356 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_schedule_onetime
|
||||
short_description: Onetime schedule configuration in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_schedule feature and onetime category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_schedule_onetime:
|
||||
description:
|
||||
- Onetime schedule configuration.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
end:
|
||||
description:
|
||||
- "Schedule end date and time, format hh:mm yyyy/mm/dd."
|
||||
type: str
|
||||
expiration_days:
|
||||
description:
|
||||
- Write an event log message this many days before the schedule expires.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Onetime schedule name.
|
||||
required: true
|
||||
type: str
|
||||
start:
|
||||
description:
|
||||
- "Schedule start date and time, format hh:mm yyyy/mm/dd."
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Onetime schedule configuration.
|
||||
fortios_firewall_schedule_onetime:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_schedule_onetime:
|
||||
color: "3"
|
||||
end: "<your_own_value>"
|
||||
expiration_days: "5"
|
||||
name: "default_name_6"
|
||||
start: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_schedule_onetime_data(json):
|
||||
option_list = ['color', 'end', 'expiration_days',
|
||||
'name', 'start']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_schedule_onetime(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_schedule_onetime'] and data['firewall_schedule_onetime']:
|
||||
state = data['firewall_schedule_onetime']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_schedule_onetime_data = data['firewall_schedule_onetime']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_schedule_onetime_data(firewall_schedule_onetime_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.schedule',
|
||||
'onetime',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.schedule',
|
||||
'onetime',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_schedule(data, fos):
|
||||
|
||||
if data['firewall_schedule_onetime']:
|
||||
resp = firewall_schedule_onetime(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_schedule_onetime": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"end": {"required": False, "type": "str"},
|
||||
"expiration_days": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"start": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,368 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_schedule_recurring
|
||||
short_description: Recurring schedule configuration in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_schedule feature and recurring category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_schedule_recurring:
|
||||
description:
|
||||
- Recurring schedule configuration.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
day:
|
||||
description:
|
||||
- One or more days of the week on which the schedule is valid. Separate the names of the days with a space.
|
||||
type: str
|
||||
choices:
|
||||
- sunday
|
||||
- monday
|
||||
- tuesday
|
||||
- wednesday
|
||||
- thursday
|
||||
- friday
|
||||
- saturday
|
||||
- none
|
||||
end:
|
||||
description:
|
||||
- "Time of day to end the schedule, format hh:mm."
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Recurring schedule name.
|
||||
required: true
|
||||
type: str
|
||||
start:
|
||||
description:
|
||||
- "Time of day to start the schedule, format hh:mm."
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Recurring schedule configuration.
|
||||
fortios_firewall_schedule_recurring:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_schedule_recurring:
|
||||
color: "3"
|
||||
day: "sunday"
|
||||
end: "<your_own_value>"
|
||||
name: "default_name_6"
|
||||
start: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_schedule_recurring_data(json):
|
||||
option_list = ['color', 'day', 'end',
|
||||
'name', 'start']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_schedule_recurring(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_schedule_recurring'] and data['firewall_schedule_recurring']:
|
||||
state = data['firewall_schedule_recurring']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_schedule_recurring_data = data['firewall_schedule_recurring']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_schedule_recurring_data(firewall_schedule_recurring_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.schedule',
|
||||
'recurring',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.schedule',
|
||||
'recurring',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_schedule(data, fos):
|
||||
|
||||
if data['firewall_schedule_recurring']:
|
||||
resp = firewall_schedule_recurring(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_schedule_recurring": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"day": {"required": False, "type": "str",
|
||||
"choices": ["sunday", "monday", "tuesday",
|
||||
"wednesday", "thursday", "friday",
|
||||
"saturday", "none"]},
|
||||
"end": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"start": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,337 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_service_category
|
||||
short_description: Configure service categories in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_service feature and category category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_service_category:
|
||||
description:
|
||||
- Configure service categories.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Service category name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure service categories.
|
||||
fortios_firewall_service_category:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_service_category:
|
||||
comment: "Comment."
|
||||
name: "default_name_4"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_service_category_data(json):
|
||||
option_list = ['comment', 'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_service_category(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_service_category'] and data['firewall_service_category']:
|
||||
state = data['firewall_service_category']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_service_category_data = data['firewall_service_category']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_service_category_data(firewall_service_category_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.service',
|
||||
'category',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.service',
|
||||
'category',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_service(data, fos):
|
||||
|
||||
if data['firewall_service_category']:
|
||||
resp = firewall_service_category(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_service_category": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,566 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_service_custom
|
||||
short_description: Configure custom services in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_service feature and custom category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_service_custom:
|
||||
description:
|
||||
- Configure custom services.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
app_category:
|
||||
description:
|
||||
- Application category ID.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application category id.
|
||||
required: true
|
||||
type: int
|
||||
app_service_type:
|
||||
description:
|
||||
- Application service type.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- app-id
|
||||
- app-category
|
||||
application:
|
||||
description:
|
||||
- Application ID.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application id.
|
||||
required: true
|
||||
type: int
|
||||
category:
|
||||
description:
|
||||
- Service category. Source firewall.service.category.name.
|
||||
type: str
|
||||
check_reset_range:
|
||||
description:
|
||||
- Configure the type of ICMP error message verification.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- strict
|
||||
- default
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
fqdn:
|
||||
description:
|
||||
- Fully qualified domain name.
|
||||
type: str
|
||||
helper:
|
||||
description:
|
||||
- Helper name.
|
||||
type: str
|
||||
choices:
|
||||
- auto
|
||||
- disable
|
||||
- ftp
|
||||
- tftp
|
||||
- ras
|
||||
- h323
|
||||
- tns
|
||||
- mms
|
||||
- sip
|
||||
- pptp
|
||||
- rtsp
|
||||
- dns-udp
|
||||
- dns-tcp
|
||||
- pmap
|
||||
- rsh
|
||||
- dcerpc
|
||||
- mgcp
|
||||
- gtp-c
|
||||
- gtp-u
|
||||
- gtp-b
|
||||
icmpcode:
|
||||
description:
|
||||
- ICMP code.
|
||||
type: int
|
||||
icmptype:
|
||||
description:
|
||||
- ICMP type.
|
||||
type: int
|
||||
iprange:
|
||||
description:
|
||||
- Start and end of the IP range associated with service.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Custom service name.
|
||||
required: true
|
||||
type: str
|
||||
protocol:
|
||||
description:
|
||||
- Protocol type based on IANA numbers.
|
||||
type: str
|
||||
choices:
|
||||
- TCP/UDP/SCTP
|
||||
- ICMP
|
||||
- ICMP6
|
||||
- IP
|
||||
- HTTP
|
||||
- FTP
|
||||
- CONNECT
|
||||
- SOCKS-TCP
|
||||
- SOCKS-UDP
|
||||
- ALL
|
||||
protocol_number:
|
||||
description:
|
||||
- IP protocol number.
|
||||
type: int
|
||||
proxy:
|
||||
description:
|
||||
- Enable/disable web proxy service.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
sctp_portrange:
|
||||
description:
|
||||
- Multiple SCTP port ranges.
|
||||
type: str
|
||||
session_ttl:
|
||||
description:
|
||||
- Session TTL (300 - 604800, 0 = default).
|
||||
type: int
|
||||
tcp_halfclose_timer:
|
||||
description:
|
||||
- Wait time to close a TCP session waiting for an unanswered FIN packet (1 - 86400 sec, 0 = default).
|
||||
type: int
|
||||
tcp_halfopen_timer:
|
||||
description:
|
||||
- Wait time to close a TCP session waiting for an unanswered open session packet (1 - 86400 sec, 0 = default).
|
||||
type: int
|
||||
tcp_portrange:
|
||||
description:
|
||||
- Multiple TCP port ranges.
|
||||
type: str
|
||||
tcp_timewait_timer:
|
||||
description:
|
||||
- Set the length of the TCP TIME-WAIT state in seconds (1 - 300 sec, 0 = default).
|
||||
type: int
|
||||
udp_idle_timer:
|
||||
description:
|
||||
- UDP half close timeout (0 - 86400 sec, 0 = default).
|
||||
type: int
|
||||
udp_portrange:
|
||||
description:
|
||||
- Multiple UDP port ranges.
|
||||
type: str
|
||||
visibility:
|
||||
description:
|
||||
- Enable/disable the visibility of the service on the GUI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure custom services.
|
||||
fortios_firewall_service_custom:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_service_custom:
|
||||
app_category:
|
||||
-
|
||||
id: "4"
|
||||
app_service_type: "disable"
|
||||
application:
|
||||
-
|
||||
id: "7"
|
||||
category: "<your_own_value> (source firewall.service.category.name)"
|
||||
check_reset_range: "disable"
|
||||
color: "10"
|
||||
comment: "Comment."
|
||||
fqdn: "<your_own_value>"
|
||||
helper: "auto"
|
||||
icmpcode: "14"
|
||||
icmptype: "15"
|
||||
iprange: "<your_own_value>"
|
||||
name: "default_name_17"
|
||||
protocol: "TCP/UDP/SCTP"
|
||||
protocol_number: "19"
|
||||
proxy: "enable"
|
||||
sctp_portrange: "<your_own_value>"
|
||||
session_ttl: "22"
|
||||
tcp_halfclose_timer: "23"
|
||||
tcp_halfopen_timer: "24"
|
||||
tcp_portrange: "<your_own_value>"
|
||||
tcp_timewait_timer: "26"
|
||||
udp_idle_timer: "27"
|
||||
udp_portrange: "<your_own_value>"
|
||||
visibility: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_service_custom_data(json):
|
||||
option_list = ['app_category', 'app_service_type', 'application',
|
||||
'category', 'check_reset_range', 'color',
|
||||
'comment', 'fqdn', 'helper',
|
||||
'icmpcode', 'icmptype', 'iprange',
|
||||
'name', 'protocol', 'protocol_number',
|
||||
'proxy', 'sctp_portrange', 'session_ttl',
|
||||
'tcp_halfclose_timer', 'tcp_halfopen_timer', 'tcp_portrange',
|
||||
'tcp_timewait_timer', 'udp_idle_timer', 'udp_portrange',
|
||||
'visibility']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_service_custom(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_service_custom'] and data['firewall_service_custom']:
|
||||
state = data['firewall_service_custom']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_service_custom_data = data['firewall_service_custom']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_service_custom_data(firewall_service_custom_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.service',
|
||||
'custom',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.service',
|
||||
'custom',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_service(data, fos):
|
||||
|
||||
if data['firewall_service_custom']:
|
||||
resp = firewall_service_custom(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_service_custom": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"app_category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"app_service_type": {"required": False, "type": "str",
|
||||
"choices": ["disable", "app-id", "app-category"]},
|
||||
"application": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"category": {"required": False, "type": "str"},
|
||||
"check_reset_range": {"required": False, "type": "str",
|
||||
"choices": ["disable", "strict", "default"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"fqdn": {"required": False, "type": "str"},
|
||||
"helper": {"required": False, "type": "str",
|
||||
"choices": ["auto", "disable", "ftp",
|
||||
"tftp", "ras", "h323",
|
||||
"tns", "mms", "sip",
|
||||
"pptp", "rtsp", "dns-udp",
|
||||
"dns-tcp", "pmap", "rsh",
|
||||
"dcerpc", "mgcp", "gtp-c",
|
||||
"gtp-u", "gtp-b"]},
|
||||
"icmpcode": {"required": False, "type": "int"},
|
||||
"icmptype": {"required": False, "type": "int"},
|
||||
"iprange": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"protocol": {"required": False, "type": "str",
|
||||
"choices": ["TCP/UDP/SCTP", "ICMP", "ICMP6",
|
||||
"IP", "HTTP", "FTP",
|
||||
"CONNECT", "SOCKS-TCP", "SOCKS-UDP",
|
||||
"ALL"]},
|
||||
"protocol_number": {"required": False, "type": "int"},
|
||||
"proxy": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"sctp_portrange": {"required": False, "type": "str"},
|
||||
"session_ttl": {"required": False, "type": "int"},
|
||||
"tcp_halfclose_timer": {"required": False, "type": "int"},
|
||||
"tcp_halfopen_timer": {"required": False, "type": "int"},
|
||||
"tcp_portrange": {"required": False, "type": "str"},
|
||||
"tcp_timewait_timer": {"required": False, "type": "int"},
|
||||
"udp_idle_timer": {"required": False, "type": "int"},
|
||||
"udp_portrange": {"required": False, "type": "str"},
|
||||
"visibility": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,371 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_service_group
|
||||
short_description: Configure service groups in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_service feature and group category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_service_group:
|
||||
description:
|
||||
- Configure service groups.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
color:
|
||||
description:
|
||||
- Color of icon on the GUI.
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
member:
|
||||
description:
|
||||
- Service objects contained within the group.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- Address group name.
|
||||
required: true
|
||||
type: str
|
||||
proxy:
|
||||
description:
|
||||
- Enable/disable web proxy service group.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure service groups.
|
||||
fortios_firewall_service_group:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_service_group:
|
||||
color: "3"
|
||||
comment: "Comment."
|
||||
member:
|
||||
-
|
||||
name: "default_name_6 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
name: "default_name_7"
|
||||
proxy: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_service_group_data(json):
|
||||
option_list = ['color', 'comment', 'member',
|
||||
'name', 'proxy']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_service_group(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_service_group'] and data['firewall_service_group']:
|
||||
state = data['firewall_service_group']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_service_group_data = data['firewall_service_group']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_service_group_data(firewall_service_group_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.service',
|
||||
'group',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.service',
|
||||
'group',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_service(data, fos):
|
||||
|
||||
if data['firewall_service_group']:
|
||||
resp = firewall_service_group(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_service_group": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"color": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"member": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"proxy": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,388 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_shaper_per_ip_shaper
|
||||
short_description: Configure per-IP traffic shaper in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_shaper feature and per_ip_shaper category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_shaper_per_ip_shaper:
|
||||
description:
|
||||
- Configure per-IP traffic shaper.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
bandwidth_unit:
|
||||
description:
|
||||
- Unit of measurement for maximum bandwidth for this shaper (Kbps, Mbps or Gbps).
|
||||
type: str
|
||||
choices:
|
||||
- kbps
|
||||
- mbps
|
||||
- gbps
|
||||
diffserv_forward:
|
||||
description:
|
||||
- Enable/disable changing the Forward (original) DiffServ setting applied to traffic accepted by this shaper.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
diffserv_reverse:
|
||||
description:
|
||||
- Enable/disable changing the Reverse (reply) DiffServ setting applied to traffic accepted by this shaper.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
diffservcode_forward:
|
||||
description:
|
||||
- Forward (original) DiffServ setting to be applied to traffic accepted by this shaper.
|
||||
type: str
|
||||
diffservcode_rev:
|
||||
description:
|
||||
- Reverse (reply) DiffServ setting to be applied to traffic accepted by this shaper.
|
||||
type: str
|
||||
max_bandwidth:
|
||||
description:
|
||||
- Upper bandwidth limit enforced by this shaper (0 - 16776000). 0 means no limit. Units depend on the bandwidth-unit setting.
|
||||
type: int
|
||||
max_concurrent_session:
|
||||
description:
|
||||
- Maximum number of concurrent sessions allowed by this shaper (0 - 2097000). 0 means no limit.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Traffic shaper name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure per-IP traffic shaper.
|
||||
fortios_firewall_shaper_per_ip_shaper:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_shaper_per_ip_shaper:
|
||||
bandwidth_unit: "kbps"
|
||||
diffserv_forward: "enable"
|
||||
diffserv_reverse: "enable"
|
||||
diffservcode_forward: "<your_own_value>"
|
||||
diffservcode_rev: "<your_own_value>"
|
||||
max_bandwidth: "8"
|
||||
max_concurrent_session: "9"
|
||||
name: "default_name_10"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_shaper_per_ip_shaper_data(json):
|
||||
option_list = ['bandwidth_unit', 'diffserv_forward', 'diffserv_reverse',
|
||||
'diffservcode_forward', 'diffservcode_rev', 'max_bandwidth',
|
||||
'max_concurrent_session', 'name']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_shaper_per_ip_shaper(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_shaper_per_ip_shaper'] and data['firewall_shaper_per_ip_shaper']:
|
||||
state = data['firewall_shaper_per_ip_shaper']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_shaper_per_ip_shaper_data = data['firewall_shaper_per_ip_shaper']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_shaper_per_ip_shaper_data(firewall_shaper_per_ip_shaper_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.shaper',
|
||||
'per-ip-shaper',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.shaper',
|
||||
'per-ip-shaper',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_shaper(data, fos):
|
||||
|
||||
if data['firewall_shaper_per_ip_shaper']:
|
||||
resp = firewall_shaper_per_ip_shaper(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_shaper_per_ip_shaper": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"bandwidth_unit": {"required": False, "type": "str",
|
||||
"choices": ["kbps", "mbps", "gbps"]},
|
||||
"diffserv_forward": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"diffserv_reverse": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"diffservcode_forward": {"required": False, "type": "str"},
|
||||
"diffservcode_rev": {"required": False, "type": "str"},
|
||||
"max_bandwidth": {"required": False, "type": "int"},
|
||||
"max_concurrent_session": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,394 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_shaper_traffic_shaper
|
||||
short_description: Configure shared traffic shaper in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_shaper feature and traffic_shaper category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_shaper_traffic_shaper:
|
||||
description:
|
||||
- Configure shared traffic shaper.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
bandwidth_unit:
|
||||
description:
|
||||
- Unit of measurement for guaranteed and maximum bandwidth for this shaper (Kbps, Mbps or Gbps).
|
||||
type: str
|
||||
choices:
|
||||
- kbps
|
||||
- mbps
|
||||
- gbps
|
||||
diffserv:
|
||||
description:
|
||||
- Enable/disable changing the DiffServ setting applied to traffic accepted by this shaper.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
diffservcode:
|
||||
description:
|
||||
- DiffServ setting to be applied to traffic accepted by this shaper.
|
||||
type: str
|
||||
guaranteed_bandwidth:
|
||||
description:
|
||||
- Amount of bandwidth guaranteed for this shaper (0 - 16776000). Units depend on the bandwidth-unit setting.
|
||||
type: int
|
||||
maximum_bandwidth:
|
||||
description:
|
||||
- Upper bandwidth limit enforced by this shaper (0 - 16776000). 0 means no limit. Units depend on the bandwidth-unit setting.
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Traffic shaper name.
|
||||
required: true
|
||||
type: str
|
||||
per_policy:
|
||||
description:
|
||||
- Enable/disable applying a separate shaper for each policy. For example, if enabled the guaranteed bandwidth is applied separately for
|
||||
each policy.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
priority:
|
||||
description:
|
||||
- Higher priority traffic is more likely to be forwarded without delays and without compromising the guaranteed bandwidth.
|
||||
type: str
|
||||
choices:
|
||||
- low
|
||||
- medium
|
||||
- high
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure shared traffic shaper.
|
||||
fortios_firewall_shaper_traffic_shaper:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_shaper_traffic_shaper:
|
||||
bandwidth_unit: "kbps"
|
||||
diffserv: "enable"
|
||||
diffservcode: "<your_own_value>"
|
||||
guaranteed_bandwidth: "6"
|
||||
maximum_bandwidth: "7"
|
||||
name: "default_name_8"
|
||||
per_policy: "disable"
|
||||
priority: "low"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_shaper_traffic_shaper_data(json):
|
||||
option_list = ['bandwidth_unit', 'diffserv', 'diffservcode',
|
||||
'guaranteed_bandwidth', 'maximum_bandwidth', 'name',
|
||||
'per_policy', 'priority']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_shaper_traffic_shaper(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_shaper_traffic_shaper'] and data['firewall_shaper_traffic_shaper']:
|
||||
state = data['firewall_shaper_traffic_shaper']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_shaper_traffic_shaper_data = data['firewall_shaper_traffic_shaper']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_shaper_traffic_shaper_data(firewall_shaper_traffic_shaper_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.shaper',
|
||||
'traffic-shaper',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.shaper',
|
||||
'traffic-shaper',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_shaper(data, fos):
|
||||
|
||||
if data['firewall_shaper_traffic_shaper']:
|
||||
resp = firewall_shaper_traffic_shaper(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_shaper_traffic_shaper": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"bandwidth_unit": {"required": False, "type": "str",
|
||||
"choices": ["kbps", "mbps", "gbps"]},
|
||||
"diffserv": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"diffservcode": {"required": False, "type": "str"},
|
||||
"guaranteed_bandwidth": {"required": False, "type": "int"},
|
||||
"maximum_bandwidth": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"per_policy": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"priority": {"required": False, "type": "str",
|
||||
"choices": ["low", "medium", "high"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,670 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_shaping_policy
|
||||
short_description: Configure shaping policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and shaping_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_shaping_policy:
|
||||
description:
|
||||
- Configure shaping policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
app_category:
|
||||
description:
|
||||
- IDs of one or more application categories that this shaper applies application control traffic shaping to.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Category IDs.
|
||||
required: true
|
||||
type: int
|
||||
application:
|
||||
description:
|
||||
- IDs of one or more applications that this shaper applies application control traffic shaping to.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Application IDs.
|
||||
required: true
|
||||
type: int
|
||||
class_id:
|
||||
description:
|
||||
- Traffic class ID.
|
||||
type: int
|
||||
comment:
|
||||
description:
|
||||
- Comments.
|
||||
type: str
|
||||
dstaddr:
|
||||
description:
|
||||
- IPv4 destination address and address group names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
dstaddr6:
|
||||
description:
|
||||
- IPv6 destination address and address group names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
dstintf:
|
||||
description:
|
||||
- One or more outgoing (egress) interfaces.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Interface name. Source system.interface.name system.zone.name.
|
||||
required: true
|
||||
type: str
|
||||
groups:
|
||||
description:
|
||||
- Apply this traffic shaping policy to user groups that have authenticated with the FortiGate.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Group name. Source user.group.name.
|
||||
required: true
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Shaping policy ID.
|
||||
required: true
|
||||
type: int
|
||||
internet_service:
|
||||
description:
|
||||
- Enable/disable use of Internet Services for this policy. If enabled, destination address and service are not used.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
internet_service_custom:
|
||||
description:
|
||||
- Custom Internet Service name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Custom Internet Service name. Source firewall.internet-service-custom.name.
|
||||
required: true
|
||||
type: str
|
||||
internet_service_id:
|
||||
description:
|
||||
- Internet Service ID.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Internet Service ID. Source firewall.internet-service.id.
|
||||
required: true
|
||||
type: int
|
||||
internet_service_src:
|
||||
description:
|
||||
- Enable/disable use of Internet Services in source for this policy. If enabled, source address is not used.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
internet_service_src_custom:
|
||||
description:
|
||||
- Custom Internet Service source name.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Custom Internet Service name. Source firewall.internet-service-custom.name.
|
||||
required: true
|
||||
type: str
|
||||
internet_service_src_id:
|
||||
description:
|
||||
- Internet Service source ID.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- Internet Service ID. Source firewall.internet-service.id.
|
||||
required: true
|
||||
type: int
|
||||
ip_version:
|
||||
description:
|
||||
- Apply this traffic shaping policy to IPv4 or IPv6 traffic.
|
||||
type: str
|
||||
choices:
|
||||
- 4
|
||||
- 6
|
||||
per_ip_shaper:
|
||||
description:
|
||||
- Per-IP traffic shaper to apply with this policy. Source firewall.shaper.per-ip-shaper.name.
|
||||
type: str
|
||||
schedule:
|
||||
description:
|
||||
- Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Service and service group names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- IPv4 source address and address group names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr6:
|
||||
description:
|
||||
- IPv6 source address and address group names.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
|
||||
required: true
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this traffic shaping policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
traffic_shaper:
|
||||
description:
|
||||
- Traffic shaper to apply to traffic forwarded by the firewall policy. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
traffic_shaper_reverse:
|
||||
description:
|
||||
- Traffic shaper to apply to response traffic received by the firewall policy. Source firewall.shaper.traffic-shaper.name.
|
||||
type: str
|
||||
url_category:
|
||||
description:
|
||||
- IDs of one or more FortiGuard Web Filtering categories that this shaper applies traffic shaping to.
|
||||
type: list
|
||||
suboptions:
|
||||
id:
|
||||
description:
|
||||
- URL category ID.
|
||||
required: true
|
||||
type: int
|
||||
users:
|
||||
description:
|
||||
- Apply this traffic shaping policy to individual users that have authenticated with the FortiGate.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- User name. Source user.local.name.
|
||||
required: true
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure shaping policies.
|
||||
fortios_firewall_shaping_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_shaping_policy:
|
||||
app_category:
|
||||
-
|
||||
id: "4"
|
||||
application:
|
||||
-
|
||||
id: "6"
|
||||
class_id: "7"
|
||||
comment: "Comments."
|
||||
dstaddr:
|
||||
-
|
||||
name: "default_name_10 (source firewall.address.name firewall.addrgrp.name)"
|
||||
dstaddr6:
|
||||
-
|
||||
name: "default_name_12 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
dstintf:
|
||||
-
|
||||
name: "default_name_14 (source system.interface.name system.zone.name)"
|
||||
groups:
|
||||
-
|
||||
name: "default_name_16 (source user.group.name)"
|
||||
id: "17"
|
||||
internet_service: "enable"
|
||||
internet_service_custom:
|
||||
-
|
||||
name: "default_name_20 (source firewall.internet-service-custom.name)"
|
||||
internet_service_id:
|
||||
-
|
||||
id: "22 (source firewall.internet-service.id)"
|
||||
internet_service_src: "enable"
|
||||
internet_service_src_custom:
|
||||
-
|
||||
name: "default_name_25 (source firewall.internet-service-custom.name)"
|
||||
internet_service_src_id:
|
||||
-
|
||||
id: "27 (source firewall.internet-service.id)"
|
||||
ip_version: "4"
|
||||
per_ip_shaper: "<your_own_value> (source firewall.shaper.per-ip-shaper.name)"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_32 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_34 (source firewall.address.name firewall.addrgrp.name)"
|
||||
srcaddr6:
|
||||
-
|
||||
name: "default_name_36 (source firewall.address6.name firewall.addrgrp6.name)"
|
||||
status: "enable"
|
||||
traffic_shaper: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
traffic_shaper_reverse: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
|
||||
url_category:
|
||||
-
|
||||
id: "41"
|
||||
users:
|
||||
-
|
||||
name: "default_name_43 (source user.local.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_shaping_policy_data(json):
|
||||
option_list = ['app_category', 'application', 'class_id',
|
||||
'comment', 'dstaddr', 'dstaddr6',
|
||||
'dstintf', 'groups', 'id',
|
||||
'internet_service', 'internet_service_custom', 'internet_service_id',
|
||||
'internet_service_src', 'internet_service_src_custom', 'internet_service_src_id',
|
||||
'ip_version', 'per_ip_shaper', 'schedule',
|
||||
'service', 'srcaddr', 'srcaddr6',
|
||||
'status', 'traffic_shaper', 'traffic_shaper_reverse',
|
||||
'url_category', 'users']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_shaping_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_shaping_policy'] and data['firewall_shaping_policy']:
|
||||
state = data['firewall_shaping_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_shaping_policy_data = data['firewall_shaping_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_shaping_policy_data(firewall_shaping_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'shaping-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'shaping-policy',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_shaping_policy']:
|
||||
resp = firewall_shaping_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_shaping_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"app_category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"application": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"class_id": {"required": False, "type": "int"},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"dstaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"dstintf": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"groups": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"internet_service": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"internet_service_custom": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"internet_service_id": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"internet_service_src": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"internet_service_src_custom": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"internet_service_src_id": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"ip_version": {"required": False, "type": "str",
|
||||
"choices": ["4", "6"]},
|
||||
"per_ip_shaper": {"required": False, "type": "str"},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr6": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"traffic_shaper": {"required": False, "type": "str"},
|
||||
"traffic_shaper_reverse": {"required": False, "type": "str"},
|
||||
"url_category": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"id": {"required": True, "type": "int"}
|
||||
}},
|
||||
"users": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,389 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_shaping_profile
|
||||
short_description: Configure shaping profiles in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and shaping_profile category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_shaping_profile:
|
||||
description:
|
||||
- Configure shaping profiles.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
comment:
|
||||
description:
|
||||
- Comment.
|
||||
type: str
|
||||
default_class_id:
|
||||
description:
|
||||
- Default class ID to handle unclassified packets (including all local traffic).
|
||||
type: int
|
||||
profile_name:
|
||||
description:
|
||||
- Shaping profile name.
|
||||
type: str
|
||||
shaping_entries:
|
||||
description:
|
||||
- Define shaping entries of this shaping profile.
|
||||
type: list
|
||||
suboptions:
|
||||
class_id:
|
||||
description:
|
||||
- Class ID.
|
||||
type: int
|
||||
guaranteed_bandwidth_percentage:
|
||||
description:
|
||||
- Guaranteed bandwith in percentage.
|
||||
type: int
|
||||
id:
|
||||
description:
|
||||
- ID number.
|
||||
required: true
|
||||
type: int
|
||||
maximum_bandwidth_percentage:
|
||||
description:
|
||||
- Maximum bandwith in percentage.
|
||||
type: int
|
||||
priority:
|
||||
description:
|
||||
- Priority.
|
||||
type: str
|
||||
choices:
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure shaping profiles.
|
||||
fortios_firewall_shaping_profile:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_shaping_profile:
|
||||
comment: "Comment."
|
||||
default_class_id: "4"
|
||||
profile_name: "<your_own_value>"
|
||||
shaping_entries:
|
||||
-
|
||||
class_id: "7"
|
||||
guaranteed_bandwidth_percentage: "8"
|
||||
id: "9"
|
||||
maximum_bandwidth_percentage: "10"
|
||||
priority: "high"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_shaping_profile_data(json):
|
||||
option_list = ['comment', 'default_class_id', 'profile_name',
|
||||
'shaping_entries']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_shaping_profile(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_shaping_profile'] and data['firewall_shaping_profile']:
|
||||
state = data['firewall_shaping_profile']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_shaping_profile_data = data['firewall_shaping_profile']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_shaping_profile_data(firewall_shaping_profile_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'shaping-profile',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'shaping-profile',
|
||||
mkey=filtered_data['profile-name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_shaping_profile']:
|
||||
resp = firewall_shaping_profile(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_shaping_profile": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"comment": {"required": False, "type": "str"},
|
||||
"default_class_id": {"required": False, "type": "int"},
|
||||
"profile_name": {"required": False, "type": "str"},
|
||||
"shaping_entries": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"class_id": {"required": False, "type": "int"},
|
||||
"guaranteed_bandwidth_percentage": {"required": False, "type": "int"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"maximum_bandwidth_percentage": {"required": False, "type": "int"},
|
||||
"priority": {"required": False, "type": "str",
|
||||
"choices": ["high", "medium", "low"]}
|
||||
}}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,629 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_sniffer
|
||||
short_description: Configure sniffer in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and sniffer category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_sniffer:
|
||||
description:
|
||||
- Configure sniffer.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
anomaly:
|
||||
description:
|
||||
- Configuration method to edit Denial of Service (DoS) anomaly settings.
|
||||
type: list
|
||||
suboptions:
|
||||
action:
|
||||
description:
|
||||
- Action taken when the threshold is reached.
|
||||
type: str
|
||||
choices:
|
||||
- pass
|
||||
- block
|
||||
log:
|
||||
description:
|
||||
- Enable/disable anomaly logging.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
name:
|
||||
description:
|
||||
- Anomaly name.
|
||||
required: true
|
||||
type: str
|
||||
quarantine:
|
||||
description:
|
||||
- Quarantine method.
|
||||
type: str
|
||||
choices:
|
||||
- none
|
||||
- attacker
|
||||
quarantine_expiry:
|
||||
description:
|
||||
- Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m). Requires quarantine set to attacker.
|
||||
type: str
|
||||
quarantine_log:
|
||||
description:
|
||||
- Enable/disable quarantine logging.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this anomaly.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- enable
|
||||
threshold:
|
||||
description:
|
||||
- Anomaly threshold. Number of detected instances per minute that triggers the anomaly action.
|
||||
type: int
|
||||
threshold(default):
|
||||
description:
|
||||
- Number of detected instances per minute which triggers action (1 - 2147483647). Note that each anomaly has a different threshold
|
||||
value assigned to it.
|
||||
type: int
|
||||
application_list:
|
||||
description:
|
||||
- Name of an existing application list. Source application.list.name.
|
||||
type: str
|
||||
application_list_status:
|
||||
description:
|
||||
- Enable/disable application control profile.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
av_profile:
|
||||
description:
|
||||
- Name of an existing antivirus profile. Source antivirus.profile.name.
|
||||
type: str
|
||||
av_profile_status:
|
||||
description:
|
||||
- Enable/disable antivirus profile.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dlp_sensor:
|
||||
description:
|
||||
- Name of an existing DLP sensor. Source dlp.sensor.name.
|
||||
type: str
|
||||
dlp_sensor_status:
|
||||
description:
|
||||
- Enable/disable DLP sensor.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
dsri:
|
||||
description:
|
||||
- Enable/disable DSRI.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
host:
|
||||
description:
|
||||
- "Hosts to filter for in sniffer traffic (Format examples: 1.1.1.1, 2.2.2.0/24, 3.3.3.3/255.255.255.0, 4.4.4.0-4.4.4.240)."
|
||||
type: str
|
||||
id:
|
||||
description:
|
||||
- Sniffer ID.
|
||||
required: true
|
||||
type: int
|
||||
interface:
|
||||
description:
|
||||
- Interface name that traffic sniffing will take place on. Source system.interface.name.
|
||||
type: str
|
||||
ips_dos_status:
|
||||
description:
|
||||
- Enable/disable IPS DoS anomaly detection.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ips_sensor:
|
||||
description:
|
||||
- Name of an existing IPS sensor. Source ips.sensor.name.
|
||||
type: str
|
||||
ips_sensor_status:
|
||||
description:
|
||||
- Enable/disable IPS sensor.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ipv6:
|
||||
description:
|
||||
- Enable/disable sniffing IPv6 packets.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
logtraffic:
|
||||
description:
|
||||
- Either log all sessions, only sessions that have a security profile applied, or disable all logging for this policy.
|
||||
type: str
|
||||
choices:
|
||||
- all
|
||||
- utm
|
||||
- disable
|
||||
max_packet_count:
|
||||
description:
|
||||
- Maximum packet count (1 - 1000000).
|
||||
type: int
|
||||
non_ip:
|
||||
description:
|
||||
- Enable/disable sniffing non-IP packets.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
port:
|
||||
description:
|
||||
- "Ports to sniff (Format examples: 10, :20, 30:40, 50-, 100-200)."
|
||||
type: str
|
||||
protocol:
|
||||
description:
|
||||
- Integer value for the protocol type as defined by IANA (0 - 255).
|
||||
type: str
|
||||
scan_botnet_connections:
|
||||
description:
|
||||
- Enable/disable scanning of connections to Botnet servers.
|
||||
type: str
|
||||
choices:
|
||||
- disable
|
||||
- block
|
||||
- monitor
|
||||
spamfilter_profile:
|
||||
description:
|
||||
- Name of an existing spam filter profile. Source spamfilter.profile.name.
|
||||
type: str
|
||||
spamfilter_profile_status:
|
||||
description:
|
||||
- Enable/disable spam filter.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
status:
|
||||
description:
|
||||
- Enable/disable the active status of the sniffer.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
vlan:
|
||||
description:
|
||||
- List of VLANs to sniff.
|
||||
type: str
|
||||
webfilter_profile:
|
||||
description:
|
||||
- Name of an existing web filter profile. Source webfilter.profile.name.
|
||||
type: str
|
||||
webfilter_profile_status:
|
||||
description:
|
||||
- Enable/disable web filter profile.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure sniffer.
|
||||
fortios_firewall_sniffer:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_sniffer:
|
||||
anomaly:
|
||||
-
|
||||
action: "pass"
|
||||
log: "enable"
|
||||
name: "default_name_6"
|
||||
quarantine: "none"
|
||||
quarantine_expiry: "<your_own_value>"
|
||||
quarantine_log: "disable"
|
||||
status: "disable"
|
||||
threshold: "11"
|
||||
threshold(default): "12"
|
||||
application_list: "<your_own_value> (source application.list.name)"
|
||||
application_list_status: "enable"
|
||||
av_profile: "<your_own_value> (source antivirus.profile.name)"
|
||||
av_profile_status: "enable"
|
||||
dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
|
||||
dlp_sensor_status: "enable"
|
||||
dsri: "enable"
|
||||
host: "myhostname"
|
||||
id: "21"
|
||||
interface: "<your_own_value> (source system.interface.name)"
|
||||
ips_dos_status: "enable"
|
||||
ips_sensor: "<your_own_value> (source ips.sensor.name)"
|
||||
ips_sensor_status: "enable"
|
||||
ipv6: "enable"
|
||||
logtraffic: "all"
|
||||
max_packet_count: "28"
|
||||
non_ip: "enable"
|
||||
port: "<your_own_value>"
|
||||
protocol: "<your_own_value>"
|
||||
scan_botnet_connections: "disable"
|
||||
spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
|
||||
spamfilter_profile_status: "enable"
|
||||
status: "enable"
|
||||
vlan: "<your_own_value>"
|
||||
webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
|
||||
webfilter_profile_status: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_sniffer_data(json):
|
||||
option_list = ['anomaly', 'application_list', 'application_list_status',
|
||||
'av_profile', 'av_profile_status', 'dlp_sensor',
|
||||
'dlp_sensor_status', 'dsri', 'host',
|
||||
'id', 'interface', 'ips_dos_status',
|
||||
'ips_sensor', 'ips_sensor_status', 'ipv6',
|
||||
'logtraffic', 'max_packet_count', 'non_ip',
|
||||
'port', 'protocol', 'scan_botnet_connections',
|
||||
'spamfilter_profile', 'spamfilter_profile_status', 'status',
|
||||
'vlan', 'webfilter_profile', 'webfilter_profile_status']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_sniffer(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_sniffer'] and data['firewall_sniffer']:
|
||||
state = data['firewall_sniffer']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_sniffer_data = data['firewall_sniffer']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_sniffer_data(firewall_sniffer_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'sniffer',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'sniffer',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_sniffer']:
|
||||
resp = firewall_sniffer(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_sniffer": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"anomaly": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["pass", "block"]},
|
||||
"log": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"quarantine": {"required": False, "type": "str",
|
||||
"choices": ["none", "attacker"]},
|
||||
"quarantine_expiry": {"required": False, "type": "str"},
|
||||
"quarantine_log": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["disable", "enable"]},
|
||||
"threshold": {"required": False, "type": "int"},
|
||||
"threshold(default)": {"required": False, "type": "int"}
|
||||
}},
|
||||
"application_list": {"required": False, "type": "str"},
|
||||
"application_list_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"av_profile": {"required": False, "type": "str"},
|
||||
"av_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dlp_sensor": {"required": False, "type": "str"},
|
||||
"dlp_sensor_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"dsri": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"host": {"required": False, "type": "str"},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"interface": {"required": False, "type": "str"},
|
||||
"ips_dos_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ips_sensor": {"required": False, "type": "str"},
|
||||
"ips_sensor_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ipv6": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"logtraffic": {"required": False, "type": "str",
|
||||
"choices": ["all", "utm", "disable"]},
|
||||
"max_packet_count": {"required": False, "type": "int"},
|
||||
"non_ip": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"port": {"required": False, "type": "str"},
|
||||
"protocol": {"required": False, "type": "str"},
|
||||
"scan_botnet_connections": {"required": False, "type": "str",
|
||||
"choices": ["disable", "block", "monitor"]},
|
||||
"spamfilter_profile": {"required": False, "type": "str"},
|
||||
"spamfilter_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"vlan": {"required": False, "type": "str"},
|
||||
"webfilter_profile": {"required": False, "type": "str"},
|
||||
"webfilter_profile_status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,396 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ssh_host_key
|
||||
short_description: SSH proxy host public keys in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ssh feature and host_key category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ssh_host_key:
|
||||
description:
|
||||
- SSH proxy host public keys.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
hostname:
|
||||
description:
|
||||
- Hostname of the SSH server.
|
||||
type: str
|
||||
ip:
|
||||
description:
|
||||
- IP address of the SSH server.
|
||||
type: str
|
||||
name:
|
||||
description:
|
||||
- SSH public key name.
|
||||
required: true
|
||||
type: str
|
||||
nid:
|
||||
description:
|
||||
- Set the nid of the ECDSA key.
|
||||
type: str
|
||||
choices:
|
||||
- 256
|
||||
- 384
|
||||
- 521
|
||||
port:
|
||||
description:
|
||||
- Port of the SSH server.
|
||||
type: int
|
||||
public_key:
|
||||
description:
|
||||
- SSH public key.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Set the trust status of the public key.
|
||||
type: str
|
||||
choices:
|
||||
- trusted
|
||||
- revoked
|
||||
type:
|
||||
description:
|
||||
- Set the type of the public key.
|
||||
type: str
|
||||
choices:
|
||||
- RSA
|
||||
- DSA
|
||||
- ECDSA
|
||||
- ED25519
|
||||
- RSA-CA
|
||||
- DSA-CA
|
||||
- ECDSA-CA
|
||||
- ED25519-CA
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: SSH proxy host public keys.
|
||||
fortios_firewall_ssh_host_key:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ssh_host_key:
|
||||
hostname: "myhostname"
|
||||
ip: "<your_own_value>"
|
||||
name: "default_name_5"
|
||||
nid: "256"
|
||||
port: "7"
|
||||
public_key: "<your_own_value>"
|
||||
status: "trusted"
|
||||
type: "RSA"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ssh_host_key_data(json):
|
||||
option_list = ['hostname', 'ip', 'name',
|
||||
'nid', 'port', 'public_key',
|
||||
'status', 'type']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ssh_host_key(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ssh_host_key'] and data['firewall_ssh_host_key']:
|
||||
state = data['firewall_ssh_host_key']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ssh_host_key_data = data['firewall_ssh_host_key']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ssh_host_key_data(firewall_ssh_host_key_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.ssh',
|
||||
'host-key',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.ssh',
|
||||
'host-key',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ssh(data, fos):
|
||||
|
||||
if data['firewall_ssh_host_key']:
|
||||
resp = firewall_ssh_host_key(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ssh_host_key": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"hostname": {"required": False, "type": "str"},
|
||||
"ip": {"required": False, "type": "str"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"nid": {"required": False, "type": "str",
|
||||
"choices": ["256", "384", "521"]},
|
||||
"port": {"required": False, "type": "int"},
|
||||
"public_key": {"required": False, "type": "str"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["trusted", "revoked"]},
|
||||
"type": {"required": False, "type": "str",
|
||||
"choices": ["RSA", "DSA", "ECDSA",
|
||||
"ED25519", "RSA-CA", "DSA-CA",
|
||||
"ECDSA-CA", "ED25519-CA"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,360 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ssh_local_ca
|
||||
short_description: SSH proxy local CA in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ssh feature and local_ca category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ssh_local_ca:
|
||||
description:
|
||||
- SSH proxy local CA.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
name:
|
||||
description:
|
||||
- SSH proxy local CA name.
|
||||
required: true
|
||||
type: str
|
||||
password:
|
||||
description:
|
||||
- Password for SSH private key.
|
||||
type: str
|
||||
private_key:
|
||||
description:
|
||||
- SSH proxy private key, encrypted with a password.
|
||||
type: str
|
||||
public_key:
|
||||
description:
|
||||
- SSH proxy public key.
|
||||
type: str
|
||||
source:
|
||||
description:
|
||||
- SSH proxy local CA source type.
|
||||
type: str
|
||||
choices:
|
||||
- built-in
|
||||
- user
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: SSH proxy local CA.
|
||||
fortios_firewall_ssh_local_ca:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ssh_local_ca:
|
||||
name: "default_name_3"
|
||||
password: "<your_own_value>"
|
||||
private_key: "<your_own_value>"
|
||||
public_key: "<your_own_value>"
|
||||
source: "built-in"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ssh_local_ca_data(json):
|
||||
option_list = ['name', 'password', 'private_key',
|
||||
'public_key', 'source']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ssh_local_ca(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ssh_local_ca'] and data['firewall_ssh_local_ca']:
|
||||
state = data['firewall_ssh_local_ca']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ssh_local_ca_data = data['firewall_ssh_local_ca']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ssh_local_ca_data(firewall_ssh_local_ca_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.ssh',
|
||||
'local-ca',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.ssh',
|
||||
'local-ca',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ssh(data, fos):
|
||||
|
||||
if data['firewall_ssh_local_ca']:
|
||||
resp = firewall_ssh_local_ca(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ssh_local_ca": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"password": {"required": False, "type": "str"},
|
||||
"private_key": {"required": False, "type": "str"},
|
||||
"public_key": {"required": False, "type": "str"},
|
||||
"source": {"required": False, "type": "str",
|
||||
"choices": ["built-in", "user"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,360 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ssh_local_key
|
||||
short_description: SSH proxy local keys in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ssh feature and local_key category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ssh_local_key:
|
||||
description:
|
||||
- SSH proxy local keys.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
name:
|
||||
description:
|
||||
- SSH proxy local key name.
|
||||
required: true
|
||||
type: str
|
||||
password:
|
||||
description:
|
||||
- Password for SSH private key.
|
||||
type: str
|
||||
private_key:
|
||||
description:
|
||||
- SSH proxy private key, encrypted with a password.
|
||||
type: str
|
||||
public_key:
|
||||
description:
|
||||
- SSH proxy public key.
|
||||
type: str
|
||||
source:
|
||||
description:
|
||||
- SSH proxy local key source type.
|
||||
type: str
|
||||
choices:
|
||||
- built-in
|
||||
- user
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: SSH proxy local keys.
|
||||
fortios_firewall_ssh_local_key:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ssh_local_key:
|
||||
name: "default_name_3"
|
||||
password: "<your_own_value>"
|
||||
private_key: "<your_own_value>"
|
||||
public_key: "<your_own_value>"
|
||||
source: "built-in"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ssh_local_key_data(json):
|
||||
option_list = ['name', 'password', 'private_key',
|
||||
'public_key', 'source']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ssh_local_key(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ssh_local_key'] and data['firewall_ssh_local_key']:
|
||||
state = data['firewall_ssh_local_key']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ssh_local_key_data = data['firewall_ssh_local_key']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ssh_local_key_data(firewall_ssh_local_key_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall.ssh',
|
||||
'local-key',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall.ssh',
|
||||
'local-key',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ssh(data, fos):
|
||||
|
||||
if data['firewall_ssh_local_key']:
|
||||
resp = firewall_ssh_local_key(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ssh_local_key": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"password": {"required": False, "type": "str"},
|
||||
"private_key": {"required": False, "type": "str"},
|
||||
"public_key": {"required": False, "type": "str"},
|
||||
"source": {"required": False, "type": "str",
|
||||
"choices": ["built-in", "user"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,344 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ssh_setting
|
||||
short_description: SSH proxy settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ssh feature and setting category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
firewall_ssh_setting:
|
||||
description:
|
||||
- SSH proxy settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
caname:
|
||||
description:
|
||||
- CA certificate used by SSH Inspection. Source firewall.ssh.local-ca.name.
|
||||
type: str
|
||||
host_trusted_checking:
|
||||
description:
|
||||
- Enable/disable host trusted checking.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
hostkey_dsa1024:
|
||||
description:
|
||||
- DSA certificate used by SSH proxy. Source firewall.ssh.local-key.name.
|
||||
type: str
|
||||
hostkey_ecdsa256:
|
||||
description:
|
||||
- ECDSA nid256 certificate used by SSH proxy. Source firewall.ssh.local-key.name.
|
||||
type: str
|
||||
hostkey_ecdsa384:
|
||||
description:
|
||||
- ECDSA nid384 certificate used by SSH proxy. Source firewall.ssh.local-key.name.
|
||||
type: str
|
||||
hostkey_ecdsa521:
|
||||
description:
|
||||
- ECDSA nid384 certificate used by SSH proxy. Source firewall.ssh.local-key.name.
|
||||
type: str
|
||||
hostkey_ed25519:
|
||||
description:
|
||||
- ED25519 hostkey used by SSH proxy. Source firewall.ssh.local-key.name.
|
||||
type: str
|
||||
hostkey_rsa2048:
|
||||
description:
|
||||
- RSA certificate used by SSH proxy. Source firewall.ssh.local-key.name.
|
||||
type: str
|
||||
untrusted_caname:
|
||||
description:
|
||||
- Untrusted CA certificate used by SSH Inspection. Source firewall.ssh.local-ca.name.
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: SSH proxy settings.
|
||||
fortios_firewall_ssh_setting:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
firewall_ssh_setting:
|
||||
caname: "<your_own_value> (source firewall.ssh.local-ca.name)"
|
||||
host_trusted_checking: "enable"
|
||||
hostkey_dsa1024: "myhostname (source firewall.ssh.local-key.name)"
|
||||
hostkey_ecdsa256: "myhostname (source firewall.ssh.local-key.name)"
|
||||
hostkey_ecdsa384: "myhostname (source firewall.ssh.local-key.name)"
|
||||
hostkey_ecdsa521: "myhostname (source firewall.ssh.local-key.name)"
|
||||
hostkey_ed25519: "myhostname (source firewall.ssh.local-key.name)"
|
||||
hostkey_rsa2048: "myhostname (source firewall.ssh.local-key.name)"
|
||||
untrusted_caname: "<your_own_value> (source firewall.ssh.local-ca.name)"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ssh_setting_data(json):
|
||||
option_list = ['caname', 'host_trusted_checking', 'hostkey_dsa1024',
|
||||
'hostkey_ecdsa256', 'hostkey_ecdsa384', 'hostkey_ecdsa521',
|
||||
'hostkey_ed25519', 'hostkey_rsa2048', 'untrusted_caname']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ssh_setting(data, fos):
|
||||
vdom = data['vdom']
|
||||
firewall_ssh_setting_data = data['firewall_ssh_setting']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ssh_setting_data(firewall_ssh_setting_data))
|
||||
|
||||
return fos.set('firewall.ssh',
|
||||
'setting',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ssh(data, fos):
|
||||
|
||||
if data['firewall_ssh_setting']:
|
||||
resp = firewall_ssh_setting(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"firewall_ssh_setting": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"caname": {"required": False, "type": "str"},
|
||||
"host_trusted_checking": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"hostkey_dsa1024": {"required": False, "type": "str"},
|
||||
"hostkey_ecdsa256": {"required": False, "type": "str"},
|
||||
"hostkey_ecdsa384": {"required": False, "type": "str"},
|
||||
"hostkey_ecdsa521": {"required": False, "type": "str"},
|
||||
"hostkey_ed25519": {"required": False, "type": "str"},
|
||||
"hostkey_rsa2048": {"required": False, "type": "str"},
|
||||
"untrusted_caname": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,456 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ssl_server
|
||||
short_description: Configure SSL servers in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ssl_server category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ssl_server:
|
||||
description:
|
||||
- Configure SSL servers.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
add_header_x_forwarded_proto:
|
||||
description:
|
||||
- Enable/disable adding an X-Forwarded-Proto header to forwarded requests.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ip:
|
||||
description:
|
||||
- IPv4 address of the SSL server.
|
||||
type: str
|
||||
mapped_port:
|
||||
description:
|
||||
- Mapped server service port (1 - 65535).
|
||||
type: int
|
||||
name:
|
||||
description:
|
||||
- Server name.
|
||||
required: true
|
||||
type: str
|
||||
port:
|
||||
description:
|
||||
- Server service port (1 - 65535).
|
||||
type: int
|
||||
ssl_algorithm:
|
||||
description:
|
||||
- Relative strength of encryption algorithms accepted in negotiation.
|
||||
type: str
|
||||
choices:
|
||||
- high
|
||||
- medium
|
||||
- low
|
||||
ssl_cert:
|
||||
description:
|
||||
- Name of certificate for SSL connections to this server. Source vpn.certificate.local.name.
|
||||
type: str
|
||||
ssl_client_renegotiation:
|
||||
description:
|
||||
- Allow or block client renegotiation by server.
|
||||
type: str
|
||||
choices:
|
||||
- allow
|
||||
- deny
|
||||
- secure
|
||||
ssl_dh_bits:
|
||||
description:
|
||||
- Bit-size of Diffie-Hellman (DH) prime used in DHE-RSA negotiation.
|
||||
type: str
|
||||
choices:
|
||||
- 768
|
||||
- 1024
|
||||
- 1536
|
||||
- 2048
|
||||
ssl_max_version:
|
||||
description:
|
||||
- Highest SSL/TLS version to negotiate.
|
||||
type: str
|
||||
choices:
|
||||
- tls-1.0
|
||||
- tls-1.1
|
||||
- tls-1.2
|
||||
ssl_min_version:
|
||||
description:
|
||||
- Lowest SSL/TLS version to negotiate.
|
||||
type: str
|
||||
choices:
|
||||
- tls-1.0
|
||||
- tls-1.1
|
||||
- tls-1.2
|
||||
ssl_mode:
|
||||
description:
|
||||
- SSL/TLS mode for encryption and decryption of traffic.
|
||||
type: str
|
||||
choices:
|
||||
- half
|
||||
- full
|
||||
ssl_send_empty_frags:
|
||||
description:
|
||||
- Enable/disable sending empty fragments to avoid attack on CBC IV.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
url_rewrite:
|
||||
description:
|
||||
- Enable/disable rewriting the URL.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure SSL servers.
|
||||
fortios_firewall_ssl_server:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ssl_server:
|
||||
add_header_x_forwarded_proto: "enable"
|
||||
ip: "<your_own_value>"
|
||||
mapped_port: "5"
|
||||
name: "default_name_6"
|
||||
port: "7"
|
||||
ssl_algorithm: "high"
|
||||
ssl_cert: "<your_own_value> (source vpn.certificate.local.name)"
|
||||
ssl_client_renegotiation: "allow"
|
||||
ssl_dh_bits: "768"
|
||||
ssl_max_version: "tls-1.0"
|
||||
ssl_min_version: "tls-1.0"
|
||||
ssl_mode: "half"
|
||||
ssl_send_empty_frags: "enable"
|
||||
url_rewrite: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ssl_server_data(json):
|
||||
option_list = ['add_header_x_forwarded_proto', 'ip', 'mapped_port',
|
||||
'name', 'port', 'ssl_algorithm',
|
||||
'ssl_cert', 'ssl_client_renegotiation', 'ssl_dh_bits',
|
||||
'ssl_max_version', 'ssl_min_version', 'ssl_mode',
|
||||
'ssl_send_empty_frags', 'url_rewrite']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ssl_server(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ssl_server'] and data['firewall_ssl_server']:
|
||||
state = data['firewall_ssl_server']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ssl_server_data = data['firewall_ssl_server']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ssl_server_data(firewall_ssl_server_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'ssl-server',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'ssl-server',
|
||||
mkey=filtered_data['name'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ssl_server']:
|
||||
resp = firewall_ssl_server(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ssl_server": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"add_header_x_forwarded_proto": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ip": {"required": False, "type": "str"},
|
||||
"mapped_port": {"required": False, "type": "int"},
|
||||
"name": {"required": True, "type": "str"},
|
||||
"port": {"required": False, "type": "int"},
|
||||
"ssl_algorithm": {"required": False, "type": "str",
|
||||
"choices": ["high", "medium", "low"]},
|
||||
"ssl_cert": {"required": False, "type": "str"},
|
||||
"ssl_client_renegotiation": {"required": False, "type": "str",
|
||||
"choices": ["allow", "deny", "secure"]},
|
||||
"ssl_dh_bits": {"required": False, "type": "str",
|
||||
"choices": ["768", "1024", "1536",
|
||||
"2048"]},
|
||||
"ssl_max_version": {"required": False, "type": "str",
|
||||
"choices": ["tls-1.0", "tls-1.1", "tls-1.2"]},
|
||||
"ssl_min_version": {"required": False, "type": "str",
|
||||
"choices": ["tls-1.0", "tls-1.1", "tls-1.2"]},
|
||||
"ssl_mode": {"required": False, "type": "str",
|
||||
"choices": ["half", "full"]},
|
||||
"ssl_send_empty_frags": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"url_rewrite": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@ -1,372 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ssl_setting
|
||||
short_description: SSL proxy settings in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall_ssl feature and setting category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
firewall_ssl_setting:
|
||||
description:
|
||||
- SSL proxy settings.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
abbreviate_handshake:
|
||||
description:
|
||||
- Enable/disable use of SSL abbreviated handshake.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
cert_cache_capacity:
|
||||
description:
|
||||
- Maximum capacity of the host certificate cache (0 - 500).
|
||||
type: int
|
||||
cert_cache_timeout:
|
||||
description:
|
||||
- Time limit to keep certificate cache (1 - 120 min).
|
||||
type: int
|
||||
kxp_queue_threshold:
|
||||
description:
|
||||
- Maximum length of the CP KXP queue. When the queue becomes full, the proxy switches cipher functions to the main CPU (0 - 512).
|
||||
type: int
|
||||
no_matching_cipher_action:
|
||||
description:
|
||||
- Bypass or drop the connection when no matching cipher is found.
|
||||
type: str
|
||||
choices:
|
||||
- bypass
|
||||
- drop
|
||||
proxy_connect_timeout:
|
||||
description:
|
||||
- Time limit to make an internal connection to the appropriate proxy process (1 - 60 sec).
|
||||
type: int
|
||||
session_cache_capacity:
|
||||
description:
|
||||
- Capacity of the SSL session cache (--Obsolete--) (1 - 1000).
|
||||
type: int
|
||||
session_cache_timeout:
|
||||
description:
|
||||
- Time limit to keep SSL session state (1 - 60 min).
|
||||
type: int
|
||||
ssl_dh_bits:
|
||||
description:
|
||||
- Bit-size of Diffie-Hellman (DH) prime used in DHE-RSA negotiation.
|
||||
type: str
|
||||
choices:
|
||||
- 768
|
||||
- 1024
|
||||
- 1536
|
||||
- 2048
|
||||
ssl_queue_threshold:
|
||||
description:
|
||||
- Maximum length of the CP SSL queue. When the queue becomes full, the proxy switches cipher functions to the main CPU (0 - 512).
|
||||
type: int
|
||||
ssl_send_empty_frags:
|
||||
description:
|
||||
- Enable/disable sending empty fragments to avoid attack on CBC IV (for SSL 3.0 and TLS 1.0 only).
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: SSL proxy settings.
|
||||
fortios_firewall_ssl_setting:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
firewall_ssl_setting:
|
||||
abbreviate_handshake: "enable"
|
||||
cert_cache_capacity: "4"
|
||||
cert_cache_timeout: "5"
|
||||
kxp_queue_threshold: "6"
|
||||
no_matching_cipher_action: "bypass"
|
||||
proxy_connect_timeout: "8"
|
||||
session_cache_capacity: "9"
|
||||
session_cache_timeout: "10"
|
||||
ssl_dh_bits: "768"
|
||||
ssl_queue_threshold: "12"
|
||||
ssl_send_empty_frags: "enable"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ssl_setting_data(json):
|
||||
option_list = ['abbreviate_handshake', 'cert_cache_capacity', 'cert_cache_timeout',
|
||||
'kxp_queue_threshold', 'no_matching_cipher_action', 'proxy_connect_timeout',
|
||||
'session_cache_capacity', 'session_cache_timeout', 'ssl_dh_bits',
|
||||
'ssl_queue_threshold', 'ssl_send_empty_frags']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ssl_setting(data, fos):
|
||||
vdom = data['vdom']
|
||||
firewall_ssl_setting_data = data['firewall_ssl_setting']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ssl_setting_data(firewall_ssl_setting_data))
|
||||
|
||||
return fos.set('firewall.ssl',
|
||||
'setting',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall_ssl(data, fos):
|
||||
|
||||
if data['firewall_ssl_setting']:
|
||||
resp = firewall_ssl_setting(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"firewall_ssl_setting": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"abbreviate_handshake": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"cert_cache_capacity": {"required": False, "type": "int"},
|
||||
"cert_cache_timeout": {"required": False, "type": "int"},
|
||||
"kxp_queue_threshold": {"required": False, "type": "int"},
|
||||
"no_matching_cipher_action": {"required": False, "type": "str",
|
||||
"choices": ["bypass", "drop"]},
|
||||
"proxy_connect_timeout": {"required": False, "type": "int"},
|
||||
"session_cache_capacity": {"required": False, "type": "int"},
|
||||
"session_cache_timeout": {"required": False, "type": "int"},
|
||||
"ssl_dh_bits": {"required": False, "type": "str",
|
||||
"choices": ["768", "1024", "1536",
|
||||
"2048"]},
|
||||
"ssl_queue_threshold": {"required": False, "type": "int"},
|
||||
"ssl_send_empty_frags": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall_ssl(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall_ssl(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,406 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
# Copyright 2019 Fortinet, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
__metaclass__ = type
|
||||
|
||||
ANSIBLE_METADATA = {'status': ['preview'],
|
||||
'supported_by': 'community',
|
||||
'metadata_version': '1.1'}
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: fortios_firewall_ttl_policy
|
||||
short_description: Configure TTL policies in Fortinet's FortiOS and FortiGate.
|
||||
description:
|
||||
- This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
|
||||
user to set and modify firewall feature and ttl_policy category.
|
||||
Examples include all parameters and values need to be adjusted to datasources before usage.
|
||||
Tested with FOS v6.0.5
|
||||
version_added: "2.8"
|
||||
author:
|
||||
- Miguel Angel Munoz (@mamunozgonzalez)
|
||||
- Nicolas Thomas (@thomnico)
|
||||
notes:
|
||||
- Requires fortiosapi library developed by Fortinet
|
||||
- Run as a local_action in your playbook
|
||||
requirements:
|
||||
- fortiosapi>=0.9.8
|
||||
options:
|
||||
host:
|
||||
description:
|
||||
- FortiOS or FortiGate IP address.
|
||||
type: str
|
||||
required: false
|
||||
username:
|
||||
description:
|
||||
- FortiOS or FortiGate username.
|
||||
type: str
|
||||
required: false
|
||||
password:
|
||||
description:
|
||||
- FortiOS or FortiGate password.
|
||||
type: str
|
||||
default: ""
|
||||
vdom:
|
||||
description:
|
||||
- Virtual domain, among those defined previously. A vdom is a
|
||||
virtual instance of the FortiGate that can be configured and
|
||||
used as a different unit.
|
||||
type: str
|
||||
default: root
|
||||
https:
|
||||
description:
|
||||
- Indicates if the requests towards FortiGate must use HTTPS protocol.
|
||||
type: bool
|
||||
default: true
|
||||
ssl_verify:
|
||||
description:
|
||||
- Ensures FortiGate certificate must be verified by a proper CA.
|
||||
type: bool
|
||||
default: true
|
||||
version_added: 2.9
|
||||
state:
|
||||
description:
|
||||
- Indicates whether to create or remove the object.
|
||||
This attribute was present already in previous version in a deeper level.
|
||||
It has been moved out to this outer level.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
version_added: 2.9
|
||||
firewall_ttl_policy:
|
||||
description:
|
||||
- Configure TTL policies.
|
||||
default: null
|
||||
type: dict
|
||||
suboptions:
|
||||
state:
|
||||
description:
|
||||
- B(Deprecated)
|
||||
- Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
|
||||
- HORIZONTALLINE
|
||||
- Indicates whether to create or remove the object.
|
||||
type: str
|
||||
required: false
|
||||
choices:
|
||||
- present
|
||||
- absent
|
||||
action:
|
||||
description:
|
||||
- Action to be performed on traffic matching this policy .
|
||||
type: str
|
||||
choices:
|
||||
- accept
|
||||
- deny
|
||||
id:
|
||||
description:
|
||||
- ID.
|
||||
required: true
|
||||
type: int
|
||||
schedule:
|
||||
description:
|
||||
- Schedule object from available options. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group
|
||||
.name.
|
||||
type: str
|
||||
service:
|
||||
description:
|
||||
- Service object(s) from available options. Separate multiple names with a space.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Service name. Source firewall.service.custom.name firewall.service.group.name.
|
||||
required: true
|
||||
type: str
|
||||
srcaddr:
|
||||
description:
|
||||
- Source address object(s) from available options. Separate multiple names with a space.
|
||||
type: list
|
||||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- Address name. Source firewall.address.name firewall.addrgrp.name.
|
||||
required: true
|
||||
type: str
|
||||
srcintf:
|
||||
description:
|
||||
- Source interface name from available interfaces. Source system.zone.name system.interface.name.
|
||||
type: str
|
||||
status:
|
||||
description:
|
||||
- Enable/disable this TTL policy.
|
||||
type: str
|
||||
choices:
|
||||
- enable
|
||||
- disable
|
||||
ttl:
|
||||
description:
|
||||
- "Value/range to match against the packet's Time to Live value (format: ttl[ - ttl_high], 1 - 255)."
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- hosts: localhost
|
||||
vars:
|
||||
host: "192.168.122.40"
|
||||
username: "admin"
|
||||
password: ""
|
||||
vdom: "root"
|
||||
ssl_verify: "False"
|
||||
tasks:
|
||||
- name: Configure TTL policies.
|
||||
fortios_firewall_ttl_policy:
|
||||
host: "{{ host }}"
|
||||
username: "{{ username }}"
|
||||
password: "{{ password }}"
|
||||
vdom: "{{ vdom }}"
|
||||
https: "False"
|
||||
state: "present"
|
||||
firewall_ttl_policy:
|
||||
action: "accept"
|
||||
id: "4"
|
||||
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
|
||||
service:
|
||||
-
|
||||
name: "default_name_7 (source firewall.service.custom.name firewall.service.group.name)"
|
||||
srcaddr:
|
||||
-
|
||||
name: "default_name_9 (source firewall.address.name firewall.addrgrp.name)"
|
||||
srcintf: "<your_own_value> (source system.zone.name system.interface.name)"
|
||||
status: "enable"
|
||||
ttl: "<your_own_value>"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
build:
|
||||
description: Build number of the fortigate image
|
||||
returned: always
|
||||
type: str
|
||||
sample: '1547'
|
||||
http_method:
|
||||
description: Last method used to provision the content into FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: 'PUT'
|
||||
http_status:
|
||||
description: Last result given by FortiGate on last operation applied
|
||||
returned: always
|
||||
type: str
|
||||
sample: "200"
|
||||
mkey:
|
||||
description: Master key (id) used in the last call to FortiGate
|
||||
returned: success
|
||||
type: str
|
||||
sample: "id"
|
||||
name:
|
||||
description: Name of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "urlfilter"
|
||||
path:
|
||||
description: Path of the table used to fulfill the request
|
||||
returned: always
|
||||
type: str
|
||||
sample: "webfilter"
|
||||
revision:
|
||||
description: Internal revision number
|
||||
returned: always
|
||||
type: str
|
||||
sample: "17.0.2.10658"
|
||||
serial:
|
||||
description: Serial number of the unit
|
||||
returned: always
|
||||
type: str
|
||||
sample: "FGVMEVYYQT3AB5352"
|
||||
status:
|
||||
description: Indication of the operation's result
|
||||
returned: always
|
||||
type: str
|
||||
sample: "success"
|
||||
vdom:
|
||||
description: Virtual domain used
|
||||
returned: always
|
||||
type: str
|
||||
sample: "root"
|
||||
version:
|
||||
description: Version of the FortiGate
|
||||
returned: always
|
||||
type: str
|
||||
sample: "v5.6.3"
|
||||
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.connection import Connection
|
||||
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
|
||||
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
|
||||
|
||||
|
||||
def login(data, fos):
|
||||
host = data['host']
|
||||
username = data['username']
|
||||
password = data['password']
|
||||
ssl_verify = data['ssl_verify']
|
||||
|
||||
fos.debug('on')
|
||||
if 'https' in data and not data['https']:
|
||||
fos.https('off')
|
||||
else:
|
||||
fos.https('on')
|
||||
|
||||
fos.login(host, username, password, verify=ssl_verify)
|
||||
|
||||
|
||||
def filter_firewall_ttl_policy_data(json):
|
||||
option_list = ['action', 'id', 'schedule',
|
||||
'service', 'srcaddr', 'srcintf',
|
||||
'status', 'ttl']
|
||||
dictionary = {}
|
||||
|
||||
for attribute in option_list:
|
||||
if attribute in json and json[attribute] is not None:
|
||||
dictionary[attribute] = json[attribute]
|
||||
|
||||
return dictionary
|
||||
|
||||
|
||||
def underscore_to_hyphen(data):
|
||||
if isinstance(data, list):
|
||||
for i, elem in enumerate(data):
|
||||
data[i] = underscore_to_hyphen(elem)
|
||||
elif isinstance(data, dict):
|
||||
new_data = {}
|
||||
for k, v in data.items():
|
||||
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
|
||||
data = new_data
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def firewall_ttl_policy(data, fos):
|
||||
vdom = data['vdom']
|
||||
if 'state' in data and data['state']:
|
||||
state = data['state']
|
||||
elif 'state' in data['firewall_ttl_policy'] and data['firewall_ttl_policy']:
|
||||
state = data['firewall_ttl_policy']['state']
|
||||
else:
|
||||
state = True
|
||||
firewall_ttl_policy_data = data['firewall_ttl_policy']
|
||||
filtered_data = underscore_to_hyphen(filter_firewall_ttl_policy_data(firewall_ttl_policy_data))
|
||||
|
||||
if state == "present":
|
||||
return fos.set('firewall',
|
||||
'ttl-policy',
|
||||
data=filtered_data,
|
||||
vdom=vdom)
|
||||
|
||||
elif state == "absent":
|
||||
return fos.delete('firewall',
|
||||
'ttl-policy',
|
||||
mkey=filtered_data['id'],
|
||||
vdom=vdom)
|
||||
|
||||
|
||||
def is_successful_status(status):
|
||||
return status['status'] == "success" or \
|
||||
status['http_method'] == "DELETE" and status['http_status'] == 404
|
||||
|
||||
|
||||
def fortios_firewall(data, fos):
|
||||
|
||||
if data['firewall_ttl_policy']:
|
||||
resp = firewall_ttl_policy(data, fos)
|
||||
|
||||
return not is_successful_status(resp), \
|
||||
resp['status'] == "success", \
|
||||
resp
|
||||
|
||||
|
||||
def main():
|
||||
fields = {
|
||||
"host": {"required": False, "type": "str"},
|
||||
"username": {"required": False, "type": "str"},
|
||||
"password": {"required": False, "type": "str", "default": "", "no_log": True},
|
||||
"vdom": {"required": False, "type": "str", "default": "root"},
|
||||
"https": {"required": False, "type": "bool", "default": True},
|
||||
"ssl_verify": {"required": False, "type": "bool", "default": True},
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"firewall_ttl_policy": {
|
||||
"required": False, "type": "dict", "default": None,
|
||||
"options": {
|
||||
"state": {"required": False, "type": "str",
|
||||
"choices": ["present", "absent"]},
|
||||
"action": {"required": False, "type": "str",
|
||||
"choices": ["accept", "deny"]},
|
||||
"id": {"required": True, "type": "int"},
|
||||
"schedule": {"required": False, "type": "str"},
|
||||
"service": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcaddr": {"required": False, "type": "list",
|
||||
"options": {
|
||||
"name": {"required": True, "type": "str"}
|
||||
}},
|
||||
"srcintf": {"required": False, "type": "str"},
|
||||
"status": {"required": False, "type": "str",
|
||||
"choices": ["enable", "disable"]},
|
||||
"ttl": {"required": False, "type": "str"}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module = AnsibleModule(argument_spec=fields,
|
||||
supports_check_mode=False)
|
||||
|
||||
# legacy_mode refers to using fortiosapi instead of HTTPAPI
|
||||
legacy_mode = 'host' in module.params and module.params['host'] is not None and \
|
||||
'username' in module.params and module.params['username'] is not None and \
|
||||
'password' in module.params and module.params['password'] is not None
|
||||
|
||||
if not legacy_mode:
|
||||
if module._socket_path:
|
||||
connection = Connection(module._socket_path)
|
||||
fos = FortiOSHandler(connection)
|
||||
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
else:
|
||||
module.fail_json(**FAIL_SOCKET_MSG)
|
||||
else:
|
||||
try:
|
||||
from fortiosapi import FortiOSAPI
|
||||
except ImportError:
|
||||
module.fail_json(msg="fortiosapi module is required")
|
||||
|
||||
fos = FortiOSAPI()
|
||||
|
||||
login(module.params, fos)
|
||||
is_error, has_changed, result = fortios_firewall(module.params, fos)
|
||||
fos.logout()
|
||||
|
||||
if not is_error:
|
||||
module.exit_json(changed=has_changed, meta=result)
|
||||
else:
|
||||
module.fail_json(msg="Error in repo", meta=result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue