diff options
Diffstat (limited to 'collections-debian-merged/ansible_collections/community/fortios/plugins')
32 files changed, 21629 insertions, 0 deletions
diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/httpapi/fortianalyzer.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/httpapi/fortianalyzer.py new file mode 100644 index 00000000..0e59ea48 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/httpapi/fortianalyzer.py @@ -0,0 +1,453 @@ +# Copyright (c) 2018 Fortinet and/or its affiliates. +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +DOCUMENTATION = ''' +--- +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +name: fortianalyzer +short_description: HttpApi Plugin for Fortinet FortiAnalyzer Appliance or VM. +description: + - This HttpApi plugin provides methods to connect to Fortinet FortiAnalyzer Appliance or VM via JSON RPC API. + +''' + +import json +from ansible.plugins.httpapi import HttpApiBase +from ansible.module_utils.basic import to_text +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import BASE_HEADERS +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZBaseException +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZCommon +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZMethods + + +class HttpApi(HttpApiBase): + def __init__(self, connection): + super(HttpApi, self).__init__(connection) + self._req_id = 0 + self._sid = None + self._url = "/jsonrpc" + self._host = None + self._tools = FAZCommon + self._debug = False + self._connected_faz = None + self._last_response_msg = None + self._last_response_code = None + self._last_data_payload = None + self._last_url = None + self._last_response_raw = None + self._locked_adom_list = list() + self._locked_adoms_by_user = list() + self._uses_workspace = False + self._uses_adoms = False + self._adom_list = list() + self._logged_in_user = None + + def set_become(self, become_context): + """ + ELEVATION IS NOT REQUIRED ON FORTINET DEVICES - SKIPPED + :param become_context: Unused input. + :return: None + """ + return None + + def update_auth(self, response, response_data): + """ + TOKENS ARE NOT USED SO NO NEED TO UPDATE AUTH + :param response: Unused input. + :param response_data Unused_input. + :return: None + """ + return None + + def login(self, username, password): + """ + This function will log the plugin into FortiAnalyzer, and return the results. + :param username: Username of FortiAnalyzer Admin + :param password: Password of FortiAnalyzer Admin + + :return: Dictionary of status if it logged in or not. + """ + + self._logged_in_user = username + self.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, "sys/login/user", + passwd=password, user=username,)) + + if "FortiAnalyzer object connected to FortiAnalyzer" in self.__str__(): + # If Login worked then inspect the FortiAnalyzer for Workspace Mode, and it's system information. + self.inspect_faz() + return + else: + raise FAZBaseException(msg="Unknown error while logging in...connection was lost during login operation..." + " Exiting") + + def inspect_faz(self): + # CHECK FOR WORKSPACE MODE TO SEE IF WE HAVE TO ENABLE ADOM LOCKS + status = self.get_system_status() + if status[0] == -11: + # THE CONNECTION GOT LOST SOMEHOW, REMOVE THE SID AND REPORT BAD LOGIN + self.logout() + raise FAZBaseException(msg="Error -11 -- the Session ID was likely malformed somehow. Contact authors." + " Exiting") + elif status[0] == 0: + try: + self.check_mode() + if self._uses_adoms: + self.get_adom_list() + if self._uses_workspace: + self.get_locked_adom_list() + self._connected_faz = status[1] + self._host = self._connected_faz["Hostname"] + except Exception: + pass + return + + def logout(self): + """ + This function will logout of the FortiAnalyzer. + """ + if self.sid is not None: + # IF WE WERE USING WORKSPACES, THEN CLEAN UP OUR LOCKS IF THEY STILL EXIST + if self.uses_workspace: + self.get_lock_info() + self.run_unlock() + ret_code, response = self.send_request(FAZMethods.EXEC, + self._tools.format_request(FAZMethods.EXEC, "sys/logout")) + self.sid = None + return ret_code, response + + def send_request(self, method, params): + """ + Responsible for actual sending of data to the connection httpapi base plugin. Does some formatting as well. + :param params: A formatted dictionary that was returned by self.common_datagram_params() + before being called here. + :param method: The preferred API Request method (GET, ADD, POST, etc....) + :type method: basestring + + :return: Dictionary of status if it logged in or not. + """ + + try: + if self.sid is None and params[0]["url"] != "sys/login/user": + try: + self.connection._connect() + except Exception as err: + raise FAZBaseException( + msg="An problem happened with the httpapi plugin self-init connection process. " + "Error: " + to_text(err)) + except IndexError: + raise FAZBaseException("An attempt was made at communicating with a FAZ with " + "no valid session and an incorrectly formatted request.") + except Exception: + raise FAZBaseException("An attempt was made at communicating with a FAZ with " + "no valid session and an unexpected error was discovered.") + + self._update_request_id() + json_request = { + "method": method, + "params": params, + "session": self.sid, + "id": self.req_id, + "verbose": 1 + } + data = json.dumps(json_request, ensure_ascii=False).replace('\\\\', '\\') + try: + # Sending URL and Data in Unicode, per Ansible Specifications for Connection Plugins + response, response_data = self.connection.send(path=to_text(self._url), data=to_text(data), + headers=BASE_HEADERS) + # Get Unicode Response - Must convert from StringIO to unicode first so we can do a replace function below + result = json.loads(to_text(response_data.getvalue())) + self._update_self_from_response(result, self._url, data) + return self._handle_response(result) + except Exception as err: + raise FAZBaseException(err) + + def _handle_response(self, response): + self._set_sid(response) + if isinstance(response["result"], list): + result = response["result"][0] + else: + result = response["result"] + if "data" in result: + return result["status"]["code"], result["data"] + else: + return result["status"]["code"], result + + def _update_self_from_response(self, response, url, data): + self._last_response_raw = response + if isinstance(response["result"], list): + result = response["result"][0] + else: + result = response["result"] + if "status" in result: + self._last_response_code = result["status"]["code"] + self._last_response_msg = result["status"]["message"] + self._last_url = url + self._last_data_payload = data + + def _set_sid(self, response): + if self.sid is None and "session" in response: + self.sid = response["session"] + + def return_connected_faz(self): + """ + Returns the data stored under self._connected_faz + + :return: dict + """ + try: + if self._connected_faz: + return self._connected_faz + except Exception: + raise FAZBaseException("Couldn't Retrieve Connected FAZ Stats") + + def get_system_status(self): + """ + Returns the system status page from the FortiAnalyzer, for logging and other uses. + return: status + """ + status = self.send_request(FAZMethods.GET, self._tools.format_request(FAZMethods.GET, "sys/status")) + return status + + @property + def debug(self): + return self._debug + + @debug.setter + def debug(self, val): + self._debug = val + + @property + def req_id(self): + return self._req_id + + @req_id.setter + def req_id(self, val): + self._req_id = val + + def _update_request_id(self, reqid=0): + self.req_id = reqid if reqid != 0 else self.req_id + 1 + + @property + def sid(self): + return self._sid + + @sid.setter + def sid(self, val): + self._sid = val + + def __str__(self): + if self.sid is not None and self.connection._url is not None: + return "FortiAnalyzer object connected to FortiAnalyzer: " + to_text(self.connection._url) + return "FortiAnalyzer object with no valid connection to a FortiAnalyzer appliance." + + ################################## + # BEGIN DATABASE LOCK CONTEXT CODE + ################################## + + @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): + """ + Checks FortiAnalyzer for the use of Workspace mode + """ + url = "/cli/global/system/global" + code, resp_obj = self.send_request(FAZMethods.GET, + self._tools.format_request(FAZMethods.GET, + url, + fields=["workspace-mode", "adom-status"])) + try: + if resp_obj["workspace-mode"] == "workflow": + self.uses_workspace = True + elif resp_obj["workspace-mode"] == "disabled": + self.uses_workspace = False + except KeyError: + self.uses_workspace = False + except Exception: + raise FAZBaseException(msg="Couldn't determine workspace-mode in the plugin") + try: + if resp_obj["adom-status"] in [1, "enable"]: + self.uses_adoms = True + else: + self.uses_adoms = False + except KeyError: + self.uses_adoms = False + except Exception: + raise FAZBaseException(msg="Couldn't determine adom-status in the plugin") + + def run_unlock(self): + """ + Checks for ADOM status, if locked, it will unlock + """ + for adom_locked in self._locked_adoms_by_user: + adom = adom_locked["adom"] + self.unlock_adom(adom) + + def lock_adom(self, adom=None, *args, **kwargs): + """ + Locks an ADOM for changes + """ + 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.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, url)) + 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): + """ + Unlocks an ADOM after changes + """ + 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.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, url)) + 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): + """ + Commits changes to an ADOM + """ + 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.send_request(FAZMethods.EXEC, self._tools.format_request(FAZMethods.EXEC, url)) + + def get_lock_info(self, adom=None): + """ + Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible + for some reason, then unlock it. + """ + if not adom or adom == "root": + url = "/dvmdb/adom/root/workspace/lockinfo" + else: + if adom.lower() == "global": + url = "/dvmdb/global/workspace/lockinfo/" + else: + url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(adom=adom) + datagram = {} + data = self._tools.format_request(FAZMethods.GET, url, **datagram) + resp_obj = self.send_request(FAZMethods.GET, data) + code = resp_obj[0] + if code != 0: + self._module.fail_json(msg=("An error occurred trying to get the ADOM Lock Info. Error: " + to_text(resp_obj))) + elif code == 0: + try: + if resp_obj[1]["status"]["message"] == "OK": + self._lock_info = None + except Exception: + self._lock_info = resp_obj[1] + return resp_obj + + def get_adom_list(self): + """ + Gets the list of ADOMs for the FortiAnalyzer + """ + if self.uses_adoms: + url = "/dvmdb/adom" + datagram = {} + data = self._tools.format_request(FAZMethods.GET, url, **datagram) + resp_obj = self.send_request(FAZMethods.GET, data) + code = resp_obj[0] + if code != 0: + self._module.fail_json(msg=("An error occurred trying to get the ADOM Info. Error: " + to_text(resp_obj))) + elif code == 0: + num_of_adoms = len(resp_obj[1]) + append_list = ['root', ] + for adom in resp_obj[1]: + if adom["tab_status"] != "": + append_list.append(to_text(adom["name"])) + self._adom_list = append_list + return resp_obj + + def get_locked_adom_list(self): + """ + Gets the list of locked adoms + """ + try: + locked_list = list() + locked_by_user_list = list() + for adom in self._adom_list: + adom_lock_info = self.get_lock_info(adom=adom) + try: + if adom_lock_info[1]["status"]["message"] == "OK": + continue + except Exception: + pass + try: + if adom_lock_info[1][0]["lock_user"]: + locked_list.append(to_text(adom)) + if adom_lock_info[1][0]["lock_user"] == self._logged_in_user: + locked_by_user_list.append({"adom": to_text(adom), "user": to_text(adom_lock_info[1][0]["lock_user"])}) + except Exception as err: + raise FAZBaseException(err) + self._locked_adom_list = locked_list + self._locked_adoms_by_user = locked_by_user_list + + except Exception as err: + raise FAZBaseException(msg=("An error occurred while trying to get the locked adom list. Error: " + + to_text(err))) + + ################################# + # END DATABASE LOCK CONTEXT CODE + ################################# diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/httpapi/fortimanager.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/httpapi/fortimanager.py new file mode 100644 index 00000000..bbdaacb8 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/httpapi/fortimanager.py @@ -0,0 +1,459 @@ +# Copyright (c) 2018 Fortinet and/or its affiliates. +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import (absolute_import, division, print_function) + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +name: fortimanager +short_description: HttpApi Plugin for Fortinet FortiManager Appliance or VM. +description: + - This HttpApi plugin provides methods to connect to Fortinet FortiManager Appliance or VM via JSON RPC API. +''' + +import json +from ansible.errors import AnsibleError +from ansible.plugins.httpapi import HttpApiBase +from ansible.module_utils.basic import to_text + +try: + from ansible_collections.fortinet.fortimanager.plugins.module_utils.common import BASE_HEADERS + from ansible_collections.fortinet.fortimanager.plugins.module_utils.common import FMGBaseException + from ansible_collections.fortinet.fortimanager.plugins.module_utils.common import FMGRCommon + from ansible_collections.fortinet.fortimanager.plugins.module_utils.common import FMGRMethods + HAS_FORTIMANAGER_COLLECTION = True +except ImportError: + HAS_FORTIMANAGER_COLLECTION = False + + +class HttpApi(HttpApiBase): + def __init__(self, connection): + super(HttpApi, self).__init__(connection) + self._req_id = 0 + self._sid = None + self._url = "/jsonrpc" + self._host = None + self._tools = FMGRCommon + self._debug = False + self._connected_fmgr = None + self._last_response_msg = None + self._last_response_code = None + self._last_data_payload = None + self._last_url = None + self._last_response_raw = None + self._locked_adom_list = list() + self._locked_adoms_by_user = list() + self._uses_workspace = False + self._uses_adoms = False + self._adom_list = list() + self._logged_in_user = None + if not HAS_FORTIMANAGER_COLLECTION: + raise AnsibleError("The community.fortios.fortimanager httpapi plugin requires the fortios.fortimanager collection.") + + def set_become(self, become_context): + """ + ELEVATION IS NOT REQUIRED ON FORTINET DEVICES - SKIPPED. + :param become_context: Unused input. + :return: None + """ + return None + + def update_auth(self, response, response_data): + """ + TOKENS ARE NOT USED SO NO NEED TO UPDATE AUTH. + :param response: Unused input. + :param response_data Unused_input. + :return: None + """ + return None + + def login(self, username, password): + + """ + This function will log the plugin into FortiManager, and return the results. + :param username: Username of FortiManager Admin + :param password: Password of FortiManager Admin + + :return: Dictionary of status if it logged in or not. + """ + self._logged_in_user = username + self.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, "sys/login/user", + passwd=password, user=username, )) + + if "FortiManager object connected to FortiManager" in self.__str__(): + # If Login worked, then inspect the FortiManager for Workspace Mode, and it's system information. + self.inspect_fmgr() + return + else: + raise FMGBaseException(msg="Unknown error while logging in...connection was lost during login operation...." + " Exiting") + + def inspect_fmgr(self): + # CHECK FOR WORKSPACE MODE TO SEE IF WE HAVE TO ENABLE ADOM LOCKS + status = self.get_system_status() + if status[0] == -11: + # THE CONNECTION GOT LOST SOMEHOW, REMOVE THE SID AND REPORT BAD LOGIN + self.logout() + raise FMGBaseException(msg="Error -11 -- the Session ID was likely malformed somehow. Contact authors." + " Exiting") + elif status[0] == 0: + try: + self.check_mode() + if self._uses_adoms: + self.get_adom_list() + if self._uses_workspace: + self.get_locked_adom_list() + self._connected_fmgr = status[1] + self._host = self._connected_fmgr["Hostname"] + except BaseException: + pass + return + + def logout(self): + """ + This function will logout of the FortiManager. + """ + if self.sid is not None: + # IF WE WERE USING WORKSPACES, THEN CLEAN UP OUR LOCKS IF THEY STILL EXIST + if self.uses_workspace: + self.get_lock_info() + self.run_unlock() + ret_code, response = self.send_request(FMGRMethods.EXEC, + self._tools.format_request(FMGRMethods.EXEC, "sys/logout")) + self.sid = None + return ret_code, response + + def send_request(self, method, params): + """ + Responsible for actual sending of data to the connection httpapi base plugin. Does some formatting too. + :param params: A formatted dictionary that was returned by self.common_datagram_params() + before being called here. + :param method: The preferred API Request method (GET, ADD, POST, etc....) + :type method: basestring + + :return: Dictionary of status, if it logged in or not. + """ + try: + if self.sid is None and params[0]["url"] != "sys/login/user": + try: + self.connection._connect() + except Exception as err: + raise FMGBaseException( + msg="An problem happened with the httpapi plugin self-init connection process. " + "Error: " + to_text(err)) + except IndexError: + raise FMGBaseException("An attempt was made at communicating with a FMG with " + "no valid session and an incorrectly formatted request.") + except Exception as err: + raise FMGBaseException("An attempt was made at communicating with a FMG with " + "no valid session and an unexpected error was discovered. \n Error: " + to_text(err)) + + self._update_request_id() + json_request = { + "method": method, + "params": params, + "session": self.sid, + "id": self.req_id, + "verbose": 1 + } + data = json.dumps(json_request, ensure_ascii=False).replace('\\\\', '\\') + try: + # Sending URL and Data in Unicode, per Ansible Specifications for Connection Plugins + response, response_data = self.connection.send(path=to_text(self._url), data=to_text(data), + headers=BASE_HEADERS) + # Get Unicode Response - Must convert from StringIO to unicode first so we can do a replace function below + result = json.loads(to_text(response_data.getvalue())) + self._update_self_from_response(result, self._url, data) + return self._handle_response(result) + except Exception as err: + raise FMGBaseException(err) + + def _handle_response(self, response): + self._set_sid(response) + if isinstance(response["result"], list): + result = response["result"][0] + else: + result = response["result"] + if "data" in result: + return result["status"]["code"], result["data"] + else: + return result["status"]["code"], result + + def _update_self_from_response(self, response, url, data): + self._last_response_raw = response + if isinstance(response["result"], list): + result = response["result"][0] + else: + result = response["result"] + if "status" in result: + self._last_response_code = result["status"]["code"] + self._last_response_msg = result["status"]["message"] + self._last_url = url + self._last_data_payload = data + + def _set_sid(self, response): + if self.sid is None and "session" in response: + self.sid = response["session"] + + def return_connected_fmgr(self): + """ + Returns the data stored under self._connected_fmgr + + :return: dict + """ + try: + if self._connected_fmgr: + return self._connected_fmgr + except Exception: + raise FMGBaseException("Couldn't Retrieve Connected FMGR Stats") + + def get_system_status(self): + """ + Returns the system status page from the FortiManager, for logging and other uses. + return: status + """ + status = self.send_request(FMGRMethods.GET, self._tools.format_request(FMGRMethods.GET, "sys/status")) + return status + + @property + def debug(self): + return self._debug + + @debug.setter + def debug(self, val): + self._debug = val + + @property + def req_id(self): + return self._req_id + + @req_id.setter + def req_id(self, val): + self._req_id = val + + def _update_request_id(self, reqid=0): + self.req_id = reqid if reqid != 0 else self.req_id + 1 + + @property + def sid(self): + return self._sid + + @sid.setter + def sid(self, val): + self._sid = val + + def __str__(self): + if self.sid is not None and self.connection._url is not None: + return "FortiManager object connected to FortiManager: " + to_text(self.connection._url) + return "FortiManager object with no valid connection to a FortiManager appliance." + + ################################## + # BEGIN DATABASE LOCK CONTEXT CODE + ################################## + + @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): + """ + Checks FortiManager for the use of Workspace mode + """ + url = "/cli/global/system/global" + code, resp_obj = self.send_request(FMGRMethods.GET, + self._tools.format_request(FMGRMethods.GET, + url, + fields=["workspace-mode", "adom-status"])) + try: + if resp_obj["workspace-mode"] == "workflow": + self.uses_workspace = True + elif resp_obj["workspace-mode"] == "disabled": + self.uses_workspace = False + except KeyError: + raise FMGBaseException(msg="Couldn't determine workspace-mode in the plugin") + try: + if resp_obj["adom-status"] in [1, "enable"]: + self.uses_adoms = True + else: + self.uses_adoms = False + except KeyError: + raise FMGBaseException(msg="Couldn't determine adom-status in the plugin") + + def run_unlock(self): + """ + Checks for ADOM status, if locked, it will unlock + """ + for adom_locked in self._locked_adoms_by_user: + adom = adom_locked["adom"] + self.unlock_adom(adom) + + def lock_adom(self, adom=None, *args, **kwargs): + """ + Locks an ADOM for changes + """ + 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.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, url)) + 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): + """ + Unlocks an ADOM after changes + """ + 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.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, url)) + 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): + """ + Commits changes to an ADOM + """ + 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.send_request(FMGRMethods.EXEC, self._tools.format_request(FMGRMethods.EXEC, url)) + + def get_lock_info(self, adom=None): + """ + Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible + for some reason, then unlock it. + """ + if not adom or adom == "root": + url = "/dvmdb/adom/root/workspace/lockinfo" + else: + if adom.lower() == "global": + url = "/dvmdb/global/workspace/lockinfo/" + else: + url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(adom=adom) + datagram = {} + data = self._tools.format_request(FMGRMethods.GET, url, **datagram) + resp_obj = self.send_request(FMGRMethods.GET, data) + code = resp_obj[0] + if code != 0: + self._module.fail_json(msg=("An error occurred trying to get the ADOM Lock Info. " + "Error: " + to_text(resp_obj))) + elif code == 0: + try: + if resp_obj[1]["status"]["message"] == "OK": + self._lock_info = None + except Exception: + self._lock_info = resp_obj[1] + return resp_obj + + def get_adom_list(self): + """ + Gets the list of ADOMs for the FortiManager + """ + if self.uses_adoms: + url = "/dvmdb/adom" + datagram = {} + data = self._tools.format_request(FMGRMethods.GET, url, **datagram) + resp_obj = self.send_request(FMGRMethods.GET, data) + code = resp_obj[0] + if code != 0: + self._module.fail_json(msg=("An error occurred trying to get the ADOM Info. " + "Error: " + to_text(resp_obj))) + elif code == 0: + num_of_adoms = len(resp_obj[1]) + append_list = ['root', ] + for adom in resp_obj[1]: + if adom["tab_status"] != "": + append_list.append(to_text(adom["name"])) + self._adom_list = append_list + return resp_obj + + def get_locked_adom_list(self): + """ + Gets the list of locked adoms + """ + try: + locked_list = list() + locked_by_user_list = list() + for adom in self._adom_list: + adom_lock_info = self.get_lock_info(adom=adom) + try: + if adom_lock_info[1]["status"]["message"] == "OK": + continue + except IndexError as err: + pass + try: + if adom_lock_info[1][0]["lock_user"]: + locked_list.append(to_text(adom)) + if adom_lock_info[1][0]["lock_user"] == self._logged_in_user: + locked_by_user_list.append({"adom": to_text(adom), + "user": to_text(adom_lock_info[1][0]["lock_user"])}) + except Exception as err: + raise FMGBaseException(err) + self._locked_adom_list = locked_list + self._locked_adoms_by_user = locked_by_user_list + + except Exception as err: + raise FMGBaseException(msg=("An error occurred while trying to get the locked adom list. Error: " + + to_text(err))) + + ################################ + # END DATABASE LOCK CONTEXT CODE + ################################ diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/module_utils/fortianalyzer/common.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/module_utils/fortianalyzer/common.py new file mode 100644 index 00000000..50cd95cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/module_utils/fortianalyzer/common.py @@ -0,0 +1,291 @@ +# 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 __future__ import absolute_import, division, print_function +__metaclass__ = type + + +# BEGIN STATIC DATA AND MESSAGES +class FAZMethods: + 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' +} + + +# FAZ RETURN CODES +FAZ_RC = { + "faz_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 FortiAnalyzer. Serial number already in use.", + "good_codes": [0, -20010], + "changed": False, + "stop_on_failure": False + }, + -20002: { + "msg": "Invalid Argument -- Does this Device exist on FortiAnalyzer?", + "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 FAZBaseException(Exception): + """Wrapper to catch the unexpected""" + + def __init__(self, msg=None, *args, **kwargs): + if msg is None: + msg = "An exception occurred within the fortianalyzer.py httpapi connection plugin." + super(FAZBaseException, self).__init__(msg, *args) + +# END ERROR CLASSES + + +# BEGIN CLASSES +class FAZCommon(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 FortiAnalyzer. + :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 FAZBaseException("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. FortiAnalyzer 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. FortiAnalyzer 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 diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/module_utils/fortianalyzer/fortianalyzer.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/module_utils/fortianalyzer/fortianalyzer.py new file mode 100644 index 00000000..74e85e30 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/module_utils/fortianalyzer/fortianalyzer.py @@ -0,0 +1,476 @@ +# 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 __future__ import absolute_import, division, print_function +__metaclass__ = type + + +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZ_RC +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZBaseException +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZCommon +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import scrub_dict +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZMethods + + +# 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.fortianalyzer.fortianalyzer_debug import debug_dump +# HAS_FAZ_DEBUG = True +# except: +# HAS_FAZ_DEBUG = False + + +# BEGIN HANDLER CLASSES +class FortiAnalyzerHandler(object): + def __init__(self, conn, module): + self._conn = conn + self._module = module + self._tools = FAZCommon + self._uses_workspace = None + self._uses_adoms = None + self._locked_adom_list = list() + self._lock_info = None + + self.workspace_check() + if self._uses_workspace: + self.get_lock_info(adom=self._module.paramgram["adom"]) + + 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 + """ + try: + adom = self._module.paramgram["adom"] + if self.uses_workspace and adom not in self._locked_adom_list and method != FAZMethods.GET: + self.lock_adom(adom=adom) + except BaseException as err: + raise FAZBaseException(err) + + data = self._tools.format_request(method, url, **datagram) + response = self._conn.send_request(method, data) + + try: + adom = self._module.paramgram["adom"] + if self.uses_workspace and adom in self._locked_adom_list \ + and response[0] == 0 and method != FAZMethods.GET: + self.commit_changes(adom=adom) + except BaseException as err: + raise FAZBaseException(err) + + # if HAS_FAZ_DEBUG: + # try: + # debug_dump(response, datagram, self._module.paramgram, url, method) + # except BaseException: + # pass + + return response + + def workspace_check(self): + """ + Checks FortiAnalyzer for the use of Workspace mode. + """ + url = "/cli/global/system/global" + data = {"fields": ["workspace-mode", "adom-status"]} + resp_obj = self.process_request(url, data, FAZMethods.GET) + try: + if resp_obj[1]["workspace-mode"] in ["workflow", "normal"]: + self.uses_workspace = True + elif resp_obj[1]["workspace-mode"] == "disabled": + self.uses_workspace = False + except KeyError: + self.uses_workspace = False + except BaseException as err: + raise FAZBaseException(msg="Couldn't determine workspace-mode in the plugin. Error: " + str(err)) + try: + if resp_obj[1]["adom-status"] in [1, "enable"]: + self.uses_adoms = True + else: + self.uses_adoms = False + except KeyError: + self.uses_adoms = False + except BaseException as err: + raise FAZBaseException(msg="Couldn't determine adom-status in the plugin. Error: " + str(err)) + + def run_unlock(self): + """ + Checks for ADOM status, if locked, it will unlock + """ + for adom_locked in self._locked_adom_list: + self.unlock_adom(adom_locked) + + def lock_adom(self, adom=None): + """ + Locks an ADOM for changes + """ + if not adom or adom == "root": + url = "/dvmdb/adom/root/workspace/lock" + else: + if adom.lower() == "global": + url = "/dvmdb/global/workspace/lock/" + else: + url = "/dvmdb/adom/{adom}/workspace/lock/".format(adom=adom) + datagram = {} + data = self._tools.format_request(FAZMethods.EXEC, url, **datagram) + resp_obj = self._conn.send_request(FAZMethods.EXEC, data) + code = resp_obj[0] + if code == 0 and resp_obj[1]["status"]["message"].lower() == "ok": + self.add_adom_to_lock_list(adom) + else: + lockinfo = self.get_lock_info(adom=adom) + self._module.fail_json(msg=("An error occurred trying to lock the adom. Error: " + + str(resp_obj) + ", LOCK INFO: " + str(lockinfo))) + return resp_obj + + def unlock_adom(self, adom=None): + """ + Unlocks an ADOM after changes + """ + if not adom or adom == "root": + url = "/dvmdb/adom/root/workspace/unlock" + else: + if adom.lower() == "global": + url = "/dvmdb/global/workspace/unlock/" + else: + url = "/dvmdb/adom/{adom}/workspace/unlock/".format(adom=adom) + datagram = {} + data = self._tools.format_request(FAZMethods.EXEC, url, **datagram) + resp_obj = self._conn.send_request(FAZMethods.EXEC, data) + code = resp_obj[0] + if code == 0 and resp_obj[1]["status"]["message"].lower() == "ok": + self.remove_adom_from_lock_list(adom) + else: + self._module.fail_json(msg=("An error occurred trying to unlock the adom. Error: " + str(resp_obj))) + return resp_obj + + def get_lock_info(self, adom=None): + """ + Gets ADOM lock info so it can be displayed with the error messages. Or if determined to be locked by ansible + for some reason, then unlock it. + """ + if not adom or adom == "root": + url = "/dvmdb/adom/root/workspace/lockinfo" + else: + if adom.lower() == "global": + url = "/dvmdb/global/workspace/lockinfo/" + else: + url = "/dvmdb/adom/{adom}/workspace/lockinfo/".format(adom=adom) + datagram = {} + data = self._tools.format_request(FAZMethods.GET, url, **datagram) + resp_obj = self._conn.send_request(FAZMethods.GET, data) + code = resp_obj[0] + if code != 0: + self._module.fail_json(msg=("An error occurred trying to get the ADOM Lock Info. Error: " + str(resp_obj))) + elif code == 0: + self._lock_info = resp_obj[1] + return resp_obj + + def commit_changes(self, adom=None, aux=False): + """ + Commits changes to an ADOM + """ + if not adom or adom == "root": + url = "/dvmdb/adom/root/workspace/commit" + else: + 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) + datagram = {} + data = self._tools.format_request(FAZMethods.EXEC, url, **datagram) + resp_obj = self._conn.send_request(FAZMethods.EXEC, data) + code = resp_obj[0] + if code != 0: + self._module.fail_json(msg=("An error occurred trying to commit changes to the adom. Error: " + + str(resp_obj))) + + 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 FortiAnalyzer 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 FortiAnalyzer + :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 FAZBaseException("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 FAZBaseException("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 = FAZ_RC.get('faz_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())) + + def return_response(self, 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 FortiAnalyzer + :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: + if self._uses_workspace: + try: + self.run_unlock() + except BaseException as err: + raise FAZBaseException(msg=("Couldn't unlock ADOM! Error: " + str(err))) + 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: + if self._uses_workspace: + try: + self.run_unlock() + except BaseException as err: + raise FAZBaseException(msg=("Couldn't unlock ADOM! Error: " + str(err))) + 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 + + @staticmethod + def construct_ansible_facts(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 FortiAnalyzer. + :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), + } + + if args: + facts["custom_args"] = args + if kwargs: + facts.update(kwargs) + + return facts + + @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) diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/faz_device.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/faz_device.py new file mode 100644 index 00000000..07a69557 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/faz_device.py @@ -0,0 +1,432 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: faz_device +author: Luke Weighall (@lweighall) +short_description: Add or remove device +description: + - Add or remove a device or list of devices to FortiAnalyzer Device Manager. ADOM Capable. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: true + default: root + type: str + + mode: + description: + - Add or delete devices. Or promote unregistered devices that are in the FortiAnalyzer "waiting pool" + required: false + default: add + choices: ["add", "delete", "promote"] + type: str + + device_username: + description: + - The username of the device being added to FortiAnalyzer. + required: false + type: str + + device_password: + description: + - The password of the device being added to FortiAnalyzer. + required: false + type: str + + device_ip: + description: + - The IP of the device being added to FortiAnalyzer. + required: false + type: str + + device_unique_name: + description: + - The desired "friendly" name of the device being added to FortiAnalyzer. + required: false + type: str + + device_serial: + description: + - The serial number of the device being added to FortiAnalyzer. + required: false + type: str + + os_type: + description: + - The os type of the device being added (default 0). + required: true + choices: ["unknown", "fos", "fsw", "foc", "fml", "faz", "fwb", "fch", "fct", "log", "fmg", "fsa", "fdd", "fac"] + type: str + + mgmt_mode: + description: + - Management Mode of the device you are adding. + choices: ["unreg", "fmg", "faz", "fmgfaz"] + required: true + type: str + + os_minor_vers: + description: + - Minor OS rev of the device. + required: true + type: str + + os_ver: + description: + - Major OS rev of the device + required: true + choices: ["unknown", "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0"] + type: str + + platform_str: + description: + - Required for determine the platform for VM platforms. ie FortiGate-VM64 + required: false + type: str + + faz_quota: + description: + - Specifies the quota for the device in FAZ + required: False + type: str +''' + +EXAMPLES = ''' +- name: DISCOVER AND ADD DEVICE A PHYSICAL FORTIGATE + community.fortios.faz_device: + adom: "root" + device_username: "admin" + device_password: "admin" + device_ip: "10.10.24.201" + device_unique_name: "FGT1" + device_serial: "FGVM000000117994" + state: "present" + mgmt_mode: "faz" + os_type: "fos" + os_ver: "5.0" + minor_rev: 6 + + +- name: DISCOVER AND ADD DEVICE A VIRTUAL FORTIGATE + community.fortios.faz_device: + adom: "root" + device_username: "admin" + device_password: "admin" + device_ip: "10.10.24.202" + device_unique_name: "FGT2" + mgmt_mode: "faz" + os_type: "fos" + os_ver: "5.0" + minor_rev: 6 + state: "present" + platform_str: "FortiGate-VM64" + +- name: DELETE DEVICE FGT01 + community.fortios.faz_device: + adom: "root" + device_unique_name: "ansible-fgt01" + mode: "delete" + +- name: DELETE DEVICE FGT02 + community.fortios.faz_device: + adom: "root" + device_unique_name: "ansible-fgt02" + mode: "delete" + +- name: PROMOTE FGT01 IN FAZ BY IP + community.fortios.faz_device: + adom: "root" + device_password: "fortinet" + device_ip: "10.7.220.151" + device_username: "ansible" + mgmt_mode: "faz" + mode: "promote" + + +- name: PROMOTE FGT02 IN FAZ + community.fortios.faz_device: + adom: "root" + device_password: "fortinet" + device_unique_name: "ansible-fgt02" + device_username: "ansible" + mgmt_mode: "faz" + mode: "promote" + +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.fortianalyzer import FortiAnalyzerHandler +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZBaseException +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZCommon +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAZMethods +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import DEFAULT_RESULT_OBJ +from ansible_collections.community.fortios.plugins.module_utils.fortianalyzer.common import FAIL_SOCKET_MSG + + +def faz_add_device(faz, paramgram): + """ + This method is used to add devices to the faz or delete them + """ + + datagram = { + "adom": paramgram["adom"], + "device": {"adm_usr": paramgram["device_username"], "adm_pass": paramgram["device_password"], + "ip": paramgram["ip"], "name": paramgram["device_unique_name"], + "mgmt_mode": paramgram["mgmt_mode"], "os_type": paramgram["os_type"], + "mr": paramgram["os_minor_vers"]} + } + + if paramgram["platform_str"] is not None: + datagram["device"]["platform_str"] = paramgram["platform_str"] + + if paramgram["sn"] is not None: + datagram["device"]["sn"] = paramgram["sn"] + + if paramgram["device_action"] is not None: + datagram["device"]["device_action"] = paramgram["device_action"] + + if paramgram["faz.quota"] is not None: + datagram["device"]["faz.quota"] = paramgram["faz.quota"] + + url = '/dvm/cmd/add/device/' + response = faz.process_request(url, datagram, FAZMethods.EXEC) + return response + + +def faz_delete_device(faz, paramgram): + """ + This method deletes a device from the FAZ + """ + datagram = { + "adom": paramgram["adom"], + "device": paramgram["device_unique_name"], + } + + url = '/dvm/cmd/del/device/' + response = faz.process_request(url, datagram, FAZMethods.EXEC) + return response + + +def faz_get_unknown_devices(faz): + """ + This method gets devices with an unknown management type field + """ + + faz_filter = ["mgmt_mode", "==", "0"] + + datagram = { + "filter": faz_filter + } + + url = "/dvmdb/device" + response = faz.process_request(url, datagram, FAZMethods.GET) + + return response + + +def faz_approve_unregistered_device_by_ip(faz, paramgram): + """ + This method approves unregistered devices by ip. + """ + # TRY TO FIND DETAILS ON THIS UNREGISTERED DEVICE + unknown_devices = faz_get_unknown_devices(faz) + target_device = None + if unknown_devices[0] == 0: + for device in unknown_devices[1]: + if device["ip"] == paramgram["ip"]: + target_device = device + else: + return "No devices are waiting to be registered!" + + # now that we have the target device details...fill out the datagram and make the call to promote it + if target_device is not None: + target_device_paramgram = { + "adom": paramgram["adom"], + "ip": target_device["ip"], + "device_username": paramgram["device_username"], + "device_password": paramgram["device_password"], + "device_unique_name": paramgram["device_unique_name"], + "sn": target_device["sn"], + "os_type": target_device["os_type"], + "mgmt_mode": paramgram["mgmt_mode"], + "os_minor_vers": target_device["mr"], + "os_ver": target_device["os_ver"], + "platform_str": target_device["platform_str"], + "faz.quota": target_device["faz.quota"], + "device_action": paramgram["device_action"] + } + + add_device = faz_add_device(faz, target_device_paramgram) + return add_device + + return str("Couldn't find the desired device with ip: " + str(paramgram["device_ip"])) + + +def faz_approve_unregistered_device_by_name(faz, paramgram): + # TRY TO FIND DETAILS ON THIS UNREGISTERED DEVICE + unknown_devices = faz_get_unknown_devices(faz) + target_device = None + if unknown_devices[0] == 0: + for device in unknown_devices[1]: + if device["name"] == paramgram["device_unique_name"]: + target_device = device + else: + return "No devices are waiting to be registered!" + + # now that we have the target device details...fill out the datagram and make the call to promote it + if target_device is not None: + target_device_paramgram = { + "adom": paramgram["adom"], + "ip": target_device["ip"], + "device_username": paramgram["device_username"], + "device_password": paramgram["device_password"], + "device_unique_name": paramgram["device_unique_name"], + "sn": target_device["sn"], + "os_type": target_device["os_type"], + "mgmt_mode": paramgram["mgmt_mode"], + "os_minor_vers": target_device["mr"], + "os_ver": target_device["os_ver"], + "platform_str": target_device["platform_str"], + "faz.quota": target_device["faz.quota"], + "device_action": paramgram["device_action"] + } + + add_device = faz_add_device(faz, target_device_paramgram) + return add_device + + return str("Couldn't find the desired device with name: " + str(paramgram["device_unique_name"])) + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "delete", "promote"], type="str", default="add"), + + device_ip=dict(required=False, type="str"), + device_username=dict(required=False, type="str"), + device_password=dict(required=False, type="str", no_log=True), + device_unique_name=dict(required=False, type="str"), + device_serial=dict(required=False, type="str"), + + os_type=dict(required=False, type="str", choices=["unknown", "fos", "fsw", "foc", "fml", + "faz", "fwb", "fch", "fct", "log", "fmg", + "fsa", "fdd", "fac"]), + mgmt_mode=dict(required=False, type="str", choices=["unreg", "fmg", "faz", "fmgfaz"]), + os_minor_vers=dict(required=False, type="str"), + os_ver=dict(required=False, type="str", choices=["unknown", "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "6.0"]), + platform_str=dict(required=False, type="str"), + faz_quota=dict(required=False, type="str") + ) + + required_if = [ + ['mode', 'delete', ['device_unique_name']], + ['mode', 'add', ['device_serial', 'device_username', + 'device_password', 'device_unique_name', 'device_ip', 'mgmt_mode', 'platform_str']] + + ] + + module = AnsibleModule(argument_spec, supports_check_mode=True, required_if=required_if, ) + + # START SESSION LOGIC + paramgram = { + "adom": module.params["adom"], + "mode": module.params["mode"], + "ip": module.params["device_ip"], + "device_username": module.params["device_username"], + "device_password": module.params["device_password"], + "device_unique_name": module.params["device_unique_name"], + "sn": module.params["device_serial"], + "os_type": module.params["os_type"], + "mgmt_mode": module.params["mgmt_mode"], + "os_minor_vers": module.params["os_minor_vers"], + "os_ver": module.params["os_ver"], + "platform_str": module.params["platform_str"], + "faz.quota": module.params["faz_quota"], + "device_action": None + } + # INSERT THE PARAMGRAM INTO THE MODULE SO WHEN WE PASS IT TO MOD_UTILS.FortiManagerHandler IT HAS THAT INFO + + if paramgram["mode"] == "add": + paramgram["device_action"] = "add_model" + elif paramgram["mode"] == "promote": + paramgram["device_action"] = "promote_unreg" + module.paramgram = paramgram + + # TRY TO INIT THE CONNECTION SOCKET PATH AND FortiManagerHandler OBJECT AND TOOLS + faz = None + if module._socket_path: + connection = Connection(module._socket_path) + faz = FortiAnalyzerHandler(connection, module) + faz.tools = FAZCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION + results = DEFAULT_RESULT_OBJ + + try: + if paramgram["mode"] == "add": + results = faz_add_device(faz, paramgram) + except BaseException as err: + raise FAZBaseException(msg="An error occurred trying to add the device. Error: " + str(err)) + + try: + if paramgram["mode"] == "promote": + if paramgram["ip"] is not None: + results = faz_approve_unregistered_device_by_ip(faz, paramgram) + elif paramgram["device_unique_name"] is not None: + results = faz_approve_unregistered_device_by_name(faz, paramgram) + except BaseException as err: + raise FAZBaseException(msg="An error occurred trying to promote the device. Error: " + str(err)) + + try: + if paramgram["mode"] == "delete": + results = faz_delete_device(faz, paramgram) + except BaseException as err: + raise FAZBaseException(msg="An error occurred trying to delete the device. Error: " + str(err)) + + # PROCESS RESULTS + try: + faz.govern_response(module=module, results=results, + ansible_facts=faz.construct_ansible_facts(results, module.params, paramgram)) + except BaseException as err: + raise FAZBaseException(msg="An error occurred with govern_response(). Error: " + str(err)) + + # This should only be hit if faz.govern_response is missed or failed somehow. In fact. It should never be hit. + # But it's here JIC. + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device.py new file mode 100644 index 00000000..8f0c6045 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device.py @@ -0,0 +1,296 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_device +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Add or remove device from FortiManager. +description: + - Add or remove a device or list of devices from FortiManager Device Manager using JSON RPC API. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: true + default: root + + mode: + description: + - The desired mode of the specified object. + required: false + default: add + choices: ["add", "delete"] + + blind_add: + description: + - When adding a device, module will check if it exists, and skip if it does. + - If enabled, this option will stop the module from checking if it already exists, and blindly add the device. + required: false + default: "disable" + choices: ["enable", "disable"] + + device_username: + description: + - The username of the device being added to FortiManager. + required: false + + device_password: + description: + - The password of the device being added to FortiManager. + required: false + + device_ip: + description: + - The IP of the device being added to FortiManager. Supports both IPv4 and IPv6. + required: false + + device_unique_name: + description: + - The desired "friendly" name of the device being added to FortiManager. + required: false + + device_serial: + description: + - The serial number of the device being added to FortiManager. + required: false +''' + +EXAMPLES = ''' +- name: DISCOVER AND ADD DEVICE FGT1 + community.fortios.fmgr_device: + adom: "root" + device_username: "admin" + device_password: "admin" + device_ip: "10.10.24.201" + device_unique_name: "FGT1" + device_serial: "FGVM000000117994" + mode: "add" + blind_add: "enable" + +- name: DISCOVER AND ADD DEVICE FGT2 + community.fortios.fmgr_device: + adom: "root" + device_username: "admin" + device_password: "admin" + device_ip: "10.10.24.202" + device_unique_name: "FGT2" + device_serial: "FGVM000000117992" + mode: "delete" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def discover_device(fmgr, paramgram): + """ + This method is used to discover devices before adding them to FMGR + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + + datagram = { + "odd_request_form": "True", + "device": {"adm_usr": paramgram["device_username"], + "adm_pass": paramgram["device_password"], + "ip": paramgram["device_ip"]} + } + + url = '/dvm/cmd/discover/device/' + + response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) + return response + + +def add_device(fmgr, paramgram): + """ + This method is used to add devices to the FMGR + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + + datagram = { + "adom": paramgram["adom"], + "flags": ["create_task", "nonblocking"], + "odd_request_form": "True", + "device": {"adm_usr": paramgram["device_username"], "adm_pass": paramgram["device_password"], + "ip": paramgram["device_ip"], "name": paramgram["device_unique_name"], + "sn": paramgram["device_serial"], "mgmt_mode": "fmgfaz", "flags": 24} + } + + url = '/dvm/cmd/add/device/' + response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) + return response + + +def delete_device(fmgr, paramgram): + """ + This method deletes a device from the FMGR + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + datagram = { + "adom": paramgram["adom"], + "flags": ["create_task", "nonblocking"], + "device": paramgram["device_unique_name"], + } + + url = '/dvm/cmd/del/device/' + response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) + return response + + +def get_device(fmgr, paramgram): + """ + This method attempts to find the firewall on FortiManager to see if it already exists. + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + datagram = { + "adom": paramgram["adom"], + "filter": ["name", "==", paramgram["device_unique_name"]], + } + + url = '/dvmdb/adom/{adom}/device/{name}'.format(adom=paramgram["adom"], + name=paramgram["device_unique_name"]) + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "delete"], type="str", default="add"), + blind_add=dict(choices=["enable", "disable"], type="str", default="disable"), + device_ip=dict(required=False, type="str"), + device_username=dict(required=False, type="str"), + device_password=dict(required=False, type="str", no_log=True), + device_unique_name=dict(required=True, type="str"), + device_serial=dict(required=False, type="str") + ) + + # BUILD MODULE OBJECT SO WE CAN BUILD THE PARAMGRAM + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + + # BUILD THE PARAMGRAM + paramgram = { + "device_ip": module.params["device_ip"], + "device_username": module.params["device_username"], + "device_password": module.params["device_password"], + "device_unique_name": module.params["device_unique_name"], + "device_serial": module.params["device_serial"], + "adom": module.params["adom"], + "mode": module.params["mode"] + } + + # INSERT THE PARAMGRAM INTO THE MODULE SO WHEN WE PASS IT TO MOD_UTILS.FortiManagerHandler IT HAS THAT INFO + module.paramgram = paramgram + + # TRY TO INIT THE CONNECTION SOCKET PATH AND FortiManagerHandler OBJECT AND TOOLS + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION + results = DEFAULT_RESULT_OBJ + try: + if paramgram["mode"] == "add": + # CHECK IF DEVICE EXISTS + if module.params["blind_add"] == "disable": + exists_results = get_device(fmgr, paramgram) + fmgr.govern_response(module=module, results=exists_results, good_codes=(0, -3), changed=False, + ansible_facts=fmgr.construct_ansible_facts(exists_results, + module.params, paramgram)) + + discover_results = discover_device(fmgr, paramgram) + fmgr.govern_response(module=module, results=discover_results, stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(discover_results, + module.params, paramgram)) + + if discover_results[0] == 0: + results = add_device(fmgr, paramgram) + fmgr.govern_response(module=module, results=discover_results, stop_on_success=True, + changed_if_success=True, + ansible_facts=fmgr.construct_ansible_facts(discover_results, + module.params, paramgram)) + + if paramgram["mode"] == "delete": + results = delete_device(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_config.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_config.py new file mode 100644 index 00000000..e36dad95 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_config.py @@ -0,0 +1,231 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_device_config +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Edit device configurations +description: + - Edit device configurations from FortiManager Device Manager using JSON RPC API. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + device_unique_name: + description: + - The unique device's name that you are editing. A.K.A. Friendly name of the device in FortiManager. + required: True + + device_hostname: + description: + - The device's new hostname. + required: false + + install_config: + description: + - Tells FMGR to attempt to install the config after making it. + required: false + default: disable + + interface: + description: + - The interface/port number you are editing. + required: false + + interface_ip: + description: + - The IP and subnet of the interface/port you are editing. + required: false + + interface_allow_access: + description: + - Specify what protocols are allowed on the interface, comma-separated list (see examples). + required: false +''' + +EXAMPLES = ''' +- name: CHANGE HOSTNAME + community.fortios.fmgr_device_config: + device_hostname: "ChangedbyAnsible" + device_unique_name: "FGT1" + +- name: EDIT INTERFACE INFORMATION + community.fortios.fmgr_device_config: + adom: "root" + device_unique_name: "FGT2" + interface: "port3" + interface_ip: "10.1.1.1/24" + interface_allow_access: "ping, telnet, https" + +- name: INSTALL CONFIG + community.fortios.fmgr_device_config: + adom: "root" + device_unique_name: "FGT1" + install_config: "enable" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods + + +def update_device_hostname(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + datagram = { + "hostname": paramgram["device_hostname"] + } + + url = "pm/config/device/{device_name}/global/system/global".format(device_name=paramgram["device_unique_name"]) + response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE) + return response + + +def update_device_interface(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + access_list = list() + allow_access_list = paramgram["interface_allow_access"].replace(' ', '') + access_list = allow_access_list.split(',') + + datagram = { + "allowaccess": access_list, + "ip": paramgram["interface_ip"] + } + + url = "/pm/config/device/{device_name}/global/system/interface" \ + "/{interface}".format(device_name=paramgram["device_unique_name"], interface=paramgram["interface"]) + response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE) + return response + + +def exec_config(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + datagram = { + "scope": { + "name": paramgram["device_unique_name"] + }, + "adom": paramgram["adom"], + "flags": "none" + } + + url = "/securityconsole/install/device" + response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + device_unique_name=dict(required=True, type="str"), + device_hostname=dict(required=False, type="str"), + interface=dict(required=False, type="str"), + interface_ip=dict(required=False, type="str"), + interface_allow_access=dict(required=False, type="str"), + install_config=dict(required=False, type="str", default="disable"), + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + paramgram = { + "device_unique_name": module.params["device_unique_name"], + "device_hostname": module.params["device_hostname"], + "interface": module.params["interface"], + "interface_ip": module.params["interface_ip"], + "interface_allow_access": module.params["interface_allow_access"], + "install_config": module.params["install_config"], + "adom": module.params["adom"] + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION + results = DEFAULT_RESULT_OBJ + try: + if paramgram["device_hostname"] is not None: + results = update_device_hostname(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + if paramgram["interface_ip"] is not None or paramgram["interface_allow_access"] is not None: + results = update_device_interface(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + if paramgram["install_config"] == "enable": + results = exec_config(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_group.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_group.py new file mode 100644 index 00000000..9c8c0ad6 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_group.py @@ -0,0 +1,323 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_device_group +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Alter FortiManager device groups. +description: + - Add or edit device groups and assign devices to device groups FortiManager Device Manager using JSON RPC API. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + vdom: + description: + - The VDOM of the Fortigate you want to add, must match the device in FMGR. Usually root. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + grp_name: + description: + - The name of the device group. + required: false + + grp_desc: + description: + - The description of the device group. + required: false + + grp_members: + description: + - A comma separated list of device names or device groups to be added as members to the device group. + - If Group Members are defined, and mode="delete", only group members will be removed. + - If you want to delete a group itself, you must omit this parameter from the task in playbook. + required: false + +''' + + +EXAMPLES = ''' +- name: CREATE DEVICE GROUP + community.fortios.fmgr_device_group: + grp_name: "TestGroup" + grp_desc: "CreatedbyAnsible" + adom: "ansible" + mode: "add" + +- name: CREATE DEVICE GROUP 2 + community.fortios.fmgr_device_group: + grp_name: "AnsibleGroup" + grp_desc: "CreatedbyAnsible" + adom: "ansible" + mode: "add" + +- name: ADD DEVICES TO DEVICE GROUP + community.fortios.fmgr_device_group: + mode: "add" + grp_name: "TestGroup" + grp_members: "FGT1,FGT2" + adom: "ansible" + vdom: "root" + +- name: REMOVE DEVICES TO DEVICE GROUP + community.fortios.fmgr_device_group: + mode: "delete" + grp_name: "TestGroup" + grp_members: "FGT1,FGT2" + adom: "ansible" + +- name: DELETE DEVICE GROUP + community.fortios.fmgr_device_group: + grp_name: "AnsibleGroup" + grp_desc: "CreatedbyAnsible" + mode: "delete" + adom: "ansible" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def get_groups(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + datagram = { + "method": "get" + } + + url = '/dvmdb/adom/{adom}/group'.format(adom=paramgram["adom"]) + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + return response + + +def add_device_group(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + mode = paramgram["mode"] + + datagram = { + "name": paramgram["grp_name"], + "desc": paramgram["grp_desc"], + "os_type": "fos" + } + + url = '/dvmdb/adom/{adom}/group'.format(adom=paramgram["adom"]) + + # IF MODE = SET -- USE THE 'SET' API CALL MODE + if mode == "set": + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + # IF MODE = UPDATE -- USER THE 'UPDATE' API CALL MODE + elif mode == "update": + response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE) + # IF MODE = ADD -- USE THE 'ADD' API CALL MODE + elif mode == "add": + response = fmgr.process_request(url, datagram, FMGRMethods.ADD) + + return response + + +def delete_device_group(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + + datagram = { + "adom": paramgram["adom"], + "name": paramgram["grp_name"] + } + + url = '/dvmdb/adom/{adom}/group/{grp_name}'.format(adom=paramgram["adom"], grp_name=paramgram["grp_name"]) + response = fmgr.process_request(url, datagram, FMGRMethods.DELETE) + return response + + +def add_group_member(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + device_member_list = paramgram["grp_members"].replace(' ', '') + device_member_list = device_member_list.split(',') + + for dev_name in device_member_list: + datagram = {'name': dev_name, 'vdom': paramgram["vdom"]} + + url = '/dvmdb/adom/{adom}/group/{grp_name}/object member'.format(adom=paramgram["adom"], + grp_name=paramgram["grp_name"]) + response = fmgr.process_request(url, datagram, FMGRMethods.ADD) + + return response + + +def delete_group_member(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + device_member_list = paramgram["grp_members"].replace(' ', '') + device_member_list = device_member_list.split(',') + + for dev_name in device_member_list: + datagram = {'name': dev_name, 'vdom': paramgram["vdom"]} + + url = '/dvmdb/adom/{adom}/group/{grp_name}/object member'.format(adom=paramgram["adom"], + grp_name=paramgram["grp_name"]) + response = fmgr.process_request(url, datagram, FMGRMethods.DELETE) + + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + vdom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + grp_desc=dict(required=False, type="str"), + grp_name=dict(required=True, type="str"), + grp_members=dict(required=False, type="str"), + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + paramgram = { + "mode": module.params["mode"], + "grp_name": module.params["grp_name"], + "grp_desc": module.params["grp_desc"], + "grp_members": module.params["grp_members"], + "adom": module.params["adom"], + "vdom": module.params["vdom"] + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION + results = DEFAULT_RESULT_OBJ + try: + # PROCESS THE GROUP ADDS FIRST + if paramgram["grp_name"] is not None and paramgram["mode"] in ["add", "set", "update"]: + # add device group + results = add_device_group(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + # PROCESS THE GROUP MEMBER ADDS + if paramgram["grp_members"] is not None and paramgram["mode"] in ["add", "set", "update"]: + # assign devices to device group + results = add_group_member(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + # PROCESS THE GROUP MEMBER DELETES + if paramgram["grp_members"] is not None and paramgram["mode"] == "delete": + # remove devices grom a group + results = delete_group_member(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + # PROCESS THE GROUP DELETES, ONLY IF GRP_MEMBERS IS NOT NULL TOO + if paramgram["grp_name"] is not None and paramgram["mode"] == "delete" and paramgram["grp_members"] is None: + # delete device group + results = delete_device_group(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_provision_template.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_provision_template.py new file mode 100644 index 00000000..c7188694 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_device_provision_template.py @@ -0,0 +1,1546 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_device_provision_template +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manages Device Provisioning Templates in FortiManager. +description: + - Allows the editing and assignment of device provisioning templates in FortiManager. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: true + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values. + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + device_unique_name: + description: + - The unique device's name that you are editing. + required: True + + provisioning_template: + description: + - The provisioning template you want to apply (default = default). + required: True + + provision_targets: + description: + - The friendly names of devices in FortiManager to assign the provisioning template to. CSV separated list. + required: True + + snmp_status: + description: + - Enables or disables SNMP globally. + required: False + choices: ["enable", "disable"] + + snmp_v2c_query_port: + description: + - Sets the snmp v2c community query port. + required: False + + snmp_v2c_trap_port: + description: + - Sets the snmp v2c community trap port. + required: False + + snmp_v2c_status: + description: + - Enables or disables the v2c community specified. + required: False + choices: ["enable", "disable"] + + snmp_v2c_trap_status: + description: + - Enables or disables the v2c community specified for traps. + required: False + choices: ["enable", "disable"] + + snmp_v2c_query_status: + description: + - Enables or disables the v2c community specified for queries. + required: False + choices: ["enable", "disable"] + + snmp_v2c_name: + description: + - Specifies the v2c community name. + required: False + + snmp_v2c_id: + description: + - Primary key for the snmp community. this must be unique! + required: False + + snmp_v2c_trap_src_ipv4: + description: + - Source ip the traps should come from IPv4. + required: False + + snmp_v2c_trap_hosts_ipv4: + description: > + - IPv4 addresses of the hosts that should get SNMP v2c traps, comma separated, must include mask + ("10.7.220.59 255.255.255.255, 10.7.220.60 255.255.255.255"). + required: False + + snmp_v2c_query_hosts_ipv4: + description: > + - IPv4 addresses or subnets that are allowed to query SNMP v2c, comma separated + ("10.7.220.59 255.255.255.0, 10.7.220.0 255.255.255.0"). + required: False + + snmpv3_auth_proto: + description: + - SNMPv3 auth protocol. + required: False + choices: ["md5", "sha"] + + snmpv3_auth_pwd: + description: + - SNMPv3 auth pwd __ currently not encrypted! ensure this file is locked down permissions wise! + required: False + + snmpv3_name: + description: + - SNMPv3 user name. + required: False + + snmpv3_notify_hosts: + description: + - List of ipv4 hosts to send snmpv3 traps to. Comma separated IPv4 list. + required: False + + snmpv3_priv_proto: + description: + - SNMPv3 priv protocol. + required: False + choices: ["aes", "des", "aes256", "aes256cisco"] + + snmpv3_priv_pwd: + description: + - SNMPv3 priv pwd currently not encrypted! ensure this file is locked down permissions wise! + required: False + + snmpv3_queries: + description: + - Allow snmpv3_queries. + required: False + choices: ["enable", "disable"] + + snmpv3_query_port: + description: + - SNMPv3 query port. + required: False + + snmpv3_security_level: + description: + - SNMPv3 security level. + required: False + choices: ["no-auth-no-priv", "auth-no-priv", "auth-priv"] + + snmpv3_source_ip: + description: + - SNMPv3 source ipv4 address for traps. + required: False + + snmpv3_status: + description: + - SNMPv3 user is enabled or disabled. + required: False + choices: ["enable", "disable"] + + snmpv3_trap_rport: + description: + - SNMPv3 trap remote port. + required: False + + snmpv3_trap_status: + description: + - SNMPv3 traps is enabled or disabled. + required: False + choices: ["enable", "disable"] + + syslog_port: + description: + - Syslog port that will be set. + required: False + + syslog_server: + description: + - Server the syslogs will be sent to. + required: False + + syslog_status: + description: + - Enables or disables syslogs. + required: False + choices: ["enable", "disable"] + + syslog_mode: + description: + - Remote syslog logging over UDP/Reliable TCP. + - choice | udp | Enable syslogging over UDP. + - choice | legacy-reliable | Enable legacy reliable syslogging by RFC3195 (Reliable Delivery for Syslog). + - choice | reliable | Enable reliable syslogging by RFC6587 (Transmission of Syslog Messages over TCP). + required: false + choices: ["udp", "legacy-reliable", "reliable"] + default: "udp" + + syslog_filter: + description: + - Sets the logging level for syslog. + required: False + choices: ["emergency", "alert", "critical", "error", "warning", "notification", "information", "debug"] + + syslog_facility: + description: + - Remote syslog facility. + - choice | kernel | Kernel messages. + - choice | user | Random user-level messages. + - choice | mail | Mail system. + - choice | daemon | System daemons. + - choice | auth | Security/authorization messages. + - choice | syslog | Messages generated internally by syslog. + - choice | lpr | Line printer subsystem. + - choice | news | Network news subsystem. + - choice | uucp | Network news subsystem. + - choice | cron | Clock daemon. + - choice | authpriv | Security/authorization messages (private). + - choice | ftp | FTP daemon. + - choice | ntp | NTP daemon. + - choice | audit | Log audit. + - choice | alert | Log alert. + - choice | clock | Clock daemon. + - choice | local0 | Reserved for local use. + - choice | local1 | Reserved for local use. + - choice | local2 | Reserved for local use. + - choice | local3 | Reserved for local use. + - choice | local4 | Reserved for local use. + - choice | local5 | Reserved for local use. + - choice | local6 | Reserved for local use. + - choice | local7 | Reserved for local use. + required: false + choices: ["kernel", "user", "mail", "daemon", "auth", "syslog", + "lpr", "news", "uucp", "cron", "authpriv", "ftp", "ntp", "audit", + "alert", "clock", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"] + default: "syslog" + + syslog_enc_algorithm: + description: + - Enable/disable reliable syslogging with TLS encryption. + - choice | high | SSL communication with high encryption algorithms. + - choice | low | SSL communication with low encryption algorithms. + - choice | disable | Disable SSL communication. + - choice | high-medium | SSL communication with high and medium encryption algorithms. + required: false + choices: ["high", "low", "disable", "high-medium"] + default: "disable" + + syslog_certificate: + description: + - Certificate used to communicate with Syslog server if encryption on. + required: false + + ntp_status: + description: + - Enables or disables ntp. + required: False + choices: ["enable", "disable"] + + ntp_sync_interval: + description: + - Sets the interval in minutes for ntp sync. + required: False + + ntp_type: + description: + - Enables fortiguard servers or custom servers are the ntp source. + required: False + choices: ["fortiguard", "custom"] + + ntp_server: + description: + - Only used with custom ntp_type -- specifies IP of server to sync to -- comma separated ip addresses for multiples. + required: False + + ntp_auth: + description: + - Enables or disables ntp authentication. + required: False + choices: ["enable", "disable"] + + ntp_auth_pwd: + description: + - Sets the ntp auth password. + required: False + + ntp_v3: + description: + - Enables or disables ntpv3 (default is ntpv4). + required: False + choices: ["enable", "disable"] + + admin_https_redirect: + description: + - Enables or disables https redirect from http. + required: False + choices: ["enable", "disable"] + + admin_https_port: + description: + - SSL admin gui port number. + required: False + + admin_http_port: + description: + - Non-SSL admin gui port number. + required: False + + admin_timeout: + description: + - Admin timeout in minutes. + required: False + + admin_language: + description: + - Sets the admin gui language. + required: False + choices: ["english", "simch", "japanese", "korean", "spanish", "trach", "french", "portuguese"] + + admin_switch_controller: + description: + - Enables or disables the switch controller. + required: False + choices: ["enable", "disable"] + + admin_gui_theme: + description: + - Changes the admin gui theme. + required: False + choices: ["green", "red", "blue", "melongene", "mariner"] + + admin_enable_fortiguard: + description: + - Enables FortiGuard security updates to their default settings. + required: False + choices: ["none", "direct", "this-fmg"] + + admin_fortianalyzer_target: + description: + - Configures faz target. + required: False + + admin_fortiguard_target: + description: + - Configures fortiguard target. + - admin_enable_fortiguard must be set to "direct". + required: False + + smtp_username: + description: + - SMTP auth username. + required: False + + smtp_password: + description: + - SMTP password. + required: False + + smtp_port: + description: + - SMTP port number. + required: False + + smtp_replyto: + description: + - SMTP reply to address. + required: False + + smtp_conn_sec: + description: + - defines the ssl level for smtp. + required: False + choices: ["none", "starttls", "smtps"] + + smtp_server: + description: + - SMTP server ipv4 address. + required: False + + smtp_source_ipv4: + description: + - SMTP source ip address. + required: False + + smtp_validate_cert: + description: + - Enables or disables valid certificate checking for smtp. + required: False + choices: ["enable", "disable"] + + dns_suffix: + description: + - Sets the local dns domain suffix. + required: False + + dns_primary_ipv4: + description: + - primary ipv4 dns forwarder. + required: False + + dns_secondary_ipv4: + description: + - secondary ipv4 dns forwarder. + required: False + + delete_provisioning_template: + description: + - If specified, all other options are ignored. The specified provisioning template will be deleted. + required: False + +''' + + +EXAMPLES = ''' +- name: SET SNMP SYSTEM INFO + community.fortios.fmgr_device_provision_template: + provisioning_template: "default" + snmp_status: "enable" + mode: "set" + +- name: SET SNMP SYSTEM INFO ANSIBLE ADOM + community.fortios.fmgr_device_provision_template: + provisioning_template: "default" + snmp_status: "enable" + mode: "set" + adom: "ansible" + +- name: SET SNMP SYSTEM INFO different template (SNMPv2) + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + snmp_status: "enable" + mode: "set" + adom: "ansible" + snmp_v2c_query_port: "162" + snmp_v2c_trap_port: "161" + snmp_v2c_status: "enable" + snmp_v2c_trap_status: "enable" + snmp_v2c_query_status: "enable" + snmp_v2c_name: "ansibleV2c" + snmp_v2c_id: "1" + snmp_v2c_trap_src_ipv4: "10.7.220.41" + snmp_v2c_trap_hosts_ipv4: "10.7.220.59 255.255.255.255, 10.7.220.60 255.255.255.255" + snmp_v2c_query_hosts_ipv4: "10.7.220.59 255.255.255.255, 10.7.220.0 255.255.255.0" + +- name: SET SNMP SYSTEM INFO different template (SNMPv3) + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + snmp_status: "enable" + mode: "set" + adom: "ansible" + snmpv3_auth_proto: "sha" + snmpv3_auth_pwd: "fortinet" + snmpv3_name: "ansibleSNMPv3" + snmpv3_notify_hosts: "10.7.220.59,10.7.220.60" + snmpv3_priv_proto: "aes256" + snmpv3_priv_pwd: "fortinet" + snmpv3_queries: "enable" + snmpv3_query_port: "161" + snmpv3_security_level: "auth_priv" + snmpv3_source_ip: "0.0.0.0" + snmpv3_status: "enable" + snmpv3_trap_rport: "162" + snmpv3_trap_status: "enable" + +- name: SET SYSLOG INFO + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + syslog_server: "10.7.220.59" + syslog_port: "514" + syslog_mode: "disable" + syslog_status: "enable" + syslog_filter: "information" + +- name: SET NTP TO FORTIGUARD + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + ntp_status: "enable" + ntp_sync_interval: "60" + type: "fortiguard" + +- name: SET NTP TO CUSTOM SERVER + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + ntp_status: "enable" + ntp_sync_interval: "60" + ntp_type: "custom" + ntp_server: "10.7.220.32,10.7.220.1" + ntp_auth: "enable" + ntp_auth_pwd: "fortinet" + ntp_v3: "disable" + +- name: SET ADMIN GLOBAL SETTINGS + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + admin_https_redirect: "enable" + admin_https_port: "4433" + admin_http_port: "8080" + admin_timeout: "30" + admin_language: "english" + admin_switch_controller: "enable" + admin_gui_theme: "blue" + admin_enable_fortiguard: "direct" + admin_fortiguard_target: "10.7.220.128" + admin_fortianalyzer_target: "10.7.220.61" + +- name: SET CUSTOM SMTP SERVER + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + smtp_username: "ansible" + smtp_password: "fortinet" + smtp_port: "25" + smtp_replyto: "ansible@do-not-reply.com" + smtp_conn_sec: "starttls" + smtp_server: "10.7.220.32" + smtp_source_ipv4: "0.0.0.0" + smtp_validate_cert: "disable" + +- name: SET DNS SERVERS + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + dns_suffix: "ansible.local" + dns_primary_ipv4: "8.8.8.8" + dns_secondary_ipv4: "4.4.4.4" + +- name: SET PROVISIONING TEMPLATE DEVICE TARGETS IN FORTIMANAGER + community.fortios.fmgr_device_provision_template: + provisioning_template: "ansibleTest" + mode: "set" + adom: "ansible" + provision_targets: "FGT1, FGT2" + +- name: DELETE ENTIRE PROVISIONING TEMPLATE + community.fortios.fmgr_device_provision_template: + delete_provisioning_template: "ansibleTest" + mode: "delete" + adom: "ansible" + +''' +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def get_devprof(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + response = DEFAULT_RESULT_OBJ + datagram = {} + + url = "/pm/devprof/adom/{adom}/{name}".format(adom=paramgram["adom"], name=paramgram["provisioning_template"]) + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + + return response + + +def set_devprof(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add', 'update']: + datagram = { + "name": paramgram["provisioning_template"], + "type": "devprof", + "description": "CreatedByAnsible", + } + url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"]) + + elif paramgram["mode"] == "delete": + datagram = {} + + url = "/pm/devprof/adom/{adom}/{name}".format(adom=paramgram["adom"], + name=paramgram["delete_provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def get_devprof_scope(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + response = DEFAULT_RESULT_OBJ + datagram = { + "name": paramgram["provisioning_template"], + "type": "devprof", + "description": "CreatedByAnsible", + } + + url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"]) + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + + return response + + +def set_devprof_scope(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add', 'update']: + datagram = { + "name": paramgram["provisioning_template"], + "type": "devprof", + "description": "CreatedByAnsible", + } + + targets = [] + for target in paramgram["provision_targets"].split(","): + # split the host on the space to get the mask out + new_target = {"name": target.strip()} + targets.append(new_target) + + datagram["scope member"] = targets + + url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"]) + + elif paramgram["mode"] == "delete": + datagram = { + "name": paramgram["provisioning_template"], + "type": "devprof", + "description": "CreatedByAnsible", + "scope member": paramgram["targets_to_add"] + } + + url = "/pm/devprof/adom/{adom}".format(adom=paramgram["adom"]) + + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + return response + + +def set_devprof_snmp(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + datagram = { + "status": paramgram["snmp_status"] + } + url = "/pm/config/adom/{adom}/devprof/" \ + "{provisioning_template}/system/snmp/sysinfo".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + return response + + +def set_devprof_snmp_v2c(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add', 'update']: + datagram = { + "query-v2c-port": paramgram["snmp_v2c_query_port"], + "trap-v2c-rport": paramgram["snmp_v2c_trap_port"], + "status": paramgram["snmp_v2c_status"], + "trap-v2c-status": paramgram["snmp_v2c_trap_status"], + "query-v2c-status": paramgram["snmp_v2c_query_status"], + "name": paramgram["snmp_v2c_name"], + "id": paramgram["snmp_v2c_id"], + "meta fields": dict(), + "hosts": list(), + "events": 411578417151, + "query-v1-status": 0, + "query-v1-port": 161, + "trap-v1-status": 0, + "trap-v1-lport": 162, + "trap-v1-rport": 162, + "trap-v2c-lport": 162, + } + + # BUILD THE HOST STRINGS + id_counter = 1 + if paramgram["snmp_v2c_trap_hosts_ipv4"] or paramgram["snmp_v2c_query_hosts_ipv4"]: + hosts = [] + if paramgram["snmp_v2c_query_hosts_ipv4"]: + for ipv4_host in paramgram["snmp_v2c_query_hosts_ipv4"].strip().split(","): + # split the host on the space to get the mask out + new_ipv4_host = {"ha-direct": "enable", + "host-type": "query", + "id": id_counter, + "ip": ipv4_host.strip().split(), + "meta fields": {}, + "source-ip": "0.0.0.0"} + hosts.append(new_ipv4_host) + id_counter += 1 + + if paramgram["snmp_v2c_trap_hosts_ipv4"]: + for ipv4_host in paramgram["snmp_v2c_trap_hosts_ipv4"].strip().split(","): + # split the host on the space to get the mask out + new_ipv4_host = {"ha-direct": "enable", + "host-type": "trap", + "id": id_counter, + "ip": ipv4_host.strip().split(), + "meta fields": {}, + "source-ip": paramgram["snmp_v2c_trap_src_ipv4"]} + hosts.append(new_ipv4_host) + id_counter += 1 + datagram["hosts"] = hosts + + url = "/pm/config/adom/{adom}/devprof/" \ + "{provisioning_template}/system/snmp/community".format(adom=adom, + provisioning_template=paramgram[ + "provisioning_template"]) + elif paramgram["mode"] == "delete": + datagram = { + "confirm": 1 + } + + url = "/pm/config/adom/{adom}/" \ + "devprof/{provisioning_template}/" \ + "system/snmp/community/{snmp_v2c_id}".format(adom=adom, + provisioning_template=paramgram["provisioning_template"], + snmp_v2c_id=paramgram["snmp_v2c_id"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_snmp_v3(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add', 'update']: + datagram = {} + datagram["auth-pwd"] = paramgram["snmpv3_auth_pwd"] + datagram["priv-pwd"] = paramgram["snmpv3_priv_pwd"] + datagram["trap-rport"] = paramgram["snmpv3_trap_rport"] + datagram["query-port"] = paramgram["snmpv3_query_port"] + datagram["name"] = paramgram["snmpv3_name"] + datagram["notify-hosts"] = paramgram["snmpv3_notify_hosts"].strip().split(",") + datagram["events"] = 1647387997183 + datagram["trap-lport"] = 162 + + datagram["source-ip"] = paramgram["snmpv3_source_ip"] + datagram["ha-direct"] = 0 + + url = "/pm/config/adom/{adom}/" \ + "devprof/{provisioning_template}/" \ + "system/snmp/user".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + elif paramgram["mode"] == "delete": + datagram = { + "confirm": 1 + } + + url = "/pm/config/adom/{adom}/devprof/" \ + "{provisioning_template}/system/snmp" \ + "/user/{snmpv3_name}".format(adom=adom, + provisioning_template=paramgram["provisioning_template"], + snmpv3_name=paramgram["snmpv3_name"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_syslog(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + + datagram = { + "status": paramgram["syslog_status"], + "port": paramgram["syslog_port"], + "server": paramgram["syslog_server"], + "mode": paramgram["syslog_mode"], + "facility": paramgram["syslog_facility"] + } + + if paramgram["mode"] in ['set', 'add', 'update']: + if paramgram["syslog_enc_algorithm"] in ["high", "low", "high-medium"] \ + and paramgram["syslog_certificate"] is not None: + datagram["certificate"] = paramgram["certificate"] + datagram["enc-algorithm"] = paramgram["syslog_enc_algorithm"] + + url = "/pm/config/adom/{adom}/" \ + "devprof/{provisioning_template}/" \ + "log/syslogd/setting".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + elif paramgram["mode"] == "delete": + url = "/pm/config/adom/{adom}/" \ + "devprof/{provisioning_template}/" \ + "log/syslogd/setting".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_syslog_filter(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + datagram = { + "severity": paramgram["syslog_filter"] + } + response = DEFAULT_RESULT_OBJ + + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/log/syslogd/filter".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_ntp(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + + # IF SET TO FORTIGUARD, BUILD A STRING SPECIFIC TO THAT + if paramgram["ntp_type"] == "fortiguard": + datagram = {} + if paramgram["ntp_status"] == "enable": + datagram["ntpsync"] = 1 + if paramgram["ntp_status"] == "disable": + datagram["ntpsync"] = 0 + if paramgram["ntp_sync_interval"] is None: + datagram["syncinterval"] = 1 + else: + datagram["syncinterval"] = paramgram["ntp_sync_interval"] + + datagram["type"] = 0 + + # IF THE NTP TYPE IS CUSTOM BUILD THE SERVER LIST + if paramgram["ntp_type"] == "custom": + id_counter = 0 + key_counter = 0 + ntpservers = [] + datagram = {} + if paramgram["ntp_status"] == "enable": + datagram["ntpsync"] = 1 + if paramgram["ntp_status"] == "disable": + datagram["ntpsync"] = 0 + try: + datagram["syncinterval"] = paramgram["ntp_sync_interval"] + except BaseException: + datagram["syncinterval"] = 1 + datagram["type"] = 1 + + for server in paramgram["ntp_server"].strip().split(","): + id_counter += 1 + server_fields = dict() + + key_counter += 1 + if paramgram["ntp_auth"] == "enable": + server_fields["authentication"] = 1 + server_fields["key"] = paramgram["ntp_auth_pwd"] + server_fields["key-id"] = key_counter + else: + server_fields["authentication"] = 0 + server_fields["key"] = "" + server_fields["key-id"] = key_counter + + if paramgram["ntp_v3"] == "enable": + server_fields["ntp_v3"] = 1 + else: + server_fields["ntp_v3"] = 0 + + # split the host on the space to get the mask out + new_ntp_server = {"authentication": server_fields["authentication"], + "id": id_counter, "key": server_fields["key"], + "key-id": id_counter, "ntpv3": server_fields["ntp_v3"], + "server": server} + ntpservers.append(new_ntp_server) + datagram["ntpserver"] = ntpservers + + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/system/ntp".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_admin(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + datagram = { + "admin-https-redirect": paramgram["admin_https_redirect"], + "admin-port": paramgram["admin_http_port"], + "admin-sport": paramgram["admin_https_port"], + "admintimeout": paramgram["admin_timeout"], + "language": paramgram["admin_language"], + "gui-theme": paramgram["admin_gui_theme"], + "switch-controller": paramgram["admin_switch_controller"], + } + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/system/global".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_smtp(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + datagram = { + "port": paramgram["smtp_port"], + "reply-to": paramgram["smtp_replyto"], + "server": paramgram["smtp_server"], + "source-ip": paramgram["smtp_source_ipv4"] + } + + if paramgram["smtp_username"]: + datagram["authenticate"] = 1 + datagram["username"] = paramgram["smtp_username"] + datagram["password"] = paramgram["smtp_password"] + + if paramgram["smtp_conn_sec"] == "none": + datagram["security"] = 0 + if paramgram["smtp_conn_sec"] == "starttls": + datagram["security"] = 1 + if paramgram["smtp_conn_sec"] == "smtps": + datagram["security"] = 2 + + if paramgram["smtp_validate_cert"] == "enable": + datagram["validate-server"] = 1 + else: + datagram["validate-server"] = 0 + + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/system/email-server".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_dns(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + datagram = { + "domain": paramgram["dns_suffix"], + "primary": paramgram["dns_primary_ipv4"], + "secondary": paramgram["dns_secondary_ipv4"], + } + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/system/dns".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_toggle_fg(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + response = DEFAULT_RESULT_OBJ + datagram = {} + if paramgram["admin_enable_fortiguard"] in ["direct", "this-fmg"]: + datagram["include-default-servers"] = "enable" + elif paramgram["admin_enable_fortiguard"] == "none": + datagram["include-default-servers"] = "disable" + + datagram["server-list"] = list() + + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/system/central-management".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + + return response + + +def set_devprof_fg(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + datagram = { + "target": paramgram["admin_enable_fortiguard"], + "target-ip": None + } + + if paramgram["mode"] in ['set', 'add', 'update']: + if paramgram["admin_fortiguard_target"] is not None and datagram["target"] == "direct": + datagram["target-ip"] = paramgram["admin_fortiguard_target"] + + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/device/profile/fortiguard".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def set_devprof_faz(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + paramgram["mode"] = paramgram["mode"] + adom = paramgram["adom"] + response = DEFAULT_RESULT_OBJ + datagram = { + "target-ip": paramgram["admin_fortianalyzer_target"], + "target": "others", + } + url = "/pm/config/adom/{adom}" \ + "/devprof/{provisioning_template}" \ + "/device/profile/fortianalyzer".format(adom=adom, + provisioning_template=paramgram["provisioning_template"]) + if paramgram["mode"] == "delete": + datagram["hastarget"] = "False" + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + provisioning_template=dict(required=False, type="str"), + provision_targets=dict(required=False, type="str"), + + device_unique_name=dict(required=False, type="str"), + snmp_status=dict(required=False, type="str", choices=["enable", "disable"]), + snmp_v2c_query_port=dict(required=False, type="int"), + snmp_v2c_trap_port=dict(required=False, type="int"), + snmp_v2c_status=dict(required=False, type="str", choices=["enable", "disable"]), + snmp_v2c_trap_status=dict(required=False, type="str", choices=["enable", "disable"]), + snmp_v2c_query_status=dict(required=False, type="str", choices=["enable", "disable"]), + snmp_v2c_name=dict(required=False, type="str", no_log=True), + snmp_v2c_id=dict(required=False, type="int"), + snmp_v2c_trap_src_ipv4=dict(required=False, type="str"), + snmp_v2c_trap_hosts_ipv4=dict(required=False, type="str"), + snmp_v2c_query_hosts_ipv4=dict(required=False, type="str"), + + snmpv3_auth_proto=dict(required=False, type="str", choices=["md5", "sha"]), + snmpv3_auth_pwd=dict(required=False, type="str", no_log=True), + snmpv3_name=dict(required=False, type="str"), + snmpv3_notify_hosts=dict(required=False, type="str"), + snmpv3_priv_proto=dict(required=False, type="str", choices=["aes", "des", "aes256", "aes256cisco"]), + snmpv3_priv_pwd=dict(required=False, type="str", no_log=True), + snmpv3_queries=dict(required=False, type="str", choices=["enable", "disable"]), + snmpv3_query_port=dict(required=False, type="int"), + snmpv3_security_level=dict(required=False, type="str", + choices=["no-auth-no-priv", "auth-no-priv", "auth-priv"]), + snmpv3_source_ip=dict(required=False, type="str"), + snmpv3_status=dict(required=False, type="str", choices=["enable", "disable"]), + snmpv3_trap_rport=dict(required=False, type="int"), + snmpv3_trap_status=dict(required=False, type="str", choices=["enable", "disable"]), + + syslog_port=dict(required=False, type="int"), + syslog_server=dict(required=False, type="str"), + syslog_mode=dict(required=False, type="str", choices=["udp", "legacy-reliable", "reliable"], default="udp"), + syslog_status=dict(required=False, type="str", choices=["enable", "disable"]), + syslog_filter=dict(required=False, type="str", choices=["emergency", "alert", "critical", "error", + "warning", "notification", "information", "debug"]), + syslog_enc_algorithm=dict(required=False, type="str", choices=["high", "low", "disable", "high-medium"], + default="disable"), + syslog_facility=dict(required=False, type="str", choices=["kernel", "user", "mail", "daemon", "auth", + "syslog", "lpr", "news", "uucp", "cron", "authpriv", + "ftp", "ntp", "audit", "alert", "clock", "local0", + "local1", "local2", "local3", "local4", "local5", + "local6", "local7"], default="syslog"), + syslog_certificate=dict(required=False, type="str"), + + ntp_status=dict(required=False, type="str", choices=["enable", "disable"]), + ntp_sync_interval=dict(required=False, type="int"), + ntp_type=dict(required=False, type="str", choices=["fortiguard", "custom"]), + ntp_server=dict(required=False, type="str"), + ntp_auth=dict(required=False, type="str", choices=["enable", "disable"]), + ntp_auth_pwd=dict(required=False, type="str", no_log=True), + ntp_v3=dict(required=False, type="str", choices=["enable", "disable"]), + + admin_https_redirect=dict(required=False, type="str", choices=["enable", "disable"]), + admin_https_port=dict(required=False, type="int"), + admin_http_port=dict(required=False, type="int"), + admin_timeout=dict(required=False, type="int"), + admin_language=dict(required=False, type="str", + choices=["english", "simch", "japanese", "korean", + "spanish", "trach", "french", "portuguese"]), + admin_switch_controller=dict(required=False, type="str", choices=["enable", "disable"]), + admin_gui_theme=dict(required=False, type="str", choices=["green", "red", "blue", "melongene", "mariner"]), + admin_enable_fortiguard=dict(required=False, type="str", choices=["none", "direct", "this-fmg"]), + admin_fortianalyzer_target=dict(required=False, type="str"), + admin_fortiguard_target=dict(required=False, type="str"), + + smtp_username=dict(required=False, type="str"), + smtp_password=dict(required=False, type="str", no_log=True), + smtp_port=dict(required=False, type="int"), + smtp_replyto=dict(required=False, type="str"), + smtp_conn_sec=dict(required=False, type="str", choices=["none", "starttls", "smtps"]), + smtp_server=dict(required=False, type="str"), + smtp_source_ipv4=dict(required=False, type="str"), + smtp_validate_cert=dict(required=False, type="str", choices=["enable", "disable"]), + + dns_suffix=dict(required=False, type="str"), + dns_primary_ipv4=dict(required=False, type="str"), + dns_secondary_ipv4=dict(required=False, type="str"), + delete_provisioning_template=dict(required=False, type="str") + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + paramgram = { + "adom": module.params["adom"], + "mode": module.params["mode"], + "provision_targets": module.params["provision_targets"], + "provisioning_template": module.params["provisioning_template"], + + "snmp_status": module.params["snmp_status"], + "snmp_v2c_query_port": module.params["snmp_v2c_query_port"], + "snmp_v2c_trap_port": module.params["snmp_v2c_trap_port"], + "snmp_v2c_status": module.params["snmp_v2c_status"], + "snmp_v2c_trap_status": module.params["snmp_v2c_trap_status"], + "snmp_v2c_query_status": module.params["snmp_v2c_query_status"], + "snmp_v2c_name": module.params["snmp_v2c_name"], + "snmp_v2c_id": module.params["snmp_v2c_id"], + "snmp_v2c_trap_src_ipv4": module.params["snmp_v2c_trap_src_ipv4"], + "snmp_v2c_trap_hosts_ipv4": module.params["snmp_v2c_trap_hosts_ipv4"], + "snmp_v2c_query_hosts_ipv4": module.params["snmp_v2c_query_hosts_ipv4"], + + "snmpv3_auth_proto": module.params["snmpv3_auth_proto"], + "snmpv3_auth_pwd": module.params["snmpv3_auth_pwd"], + "snmpv3_name": module.params["snmpv3_name"], + "snmpv3_notify_hosts": module.params["snmpv3_notify_hosts"], + "snmpv3_priv_proto": module.params["snmpv3_priv_proto"], + "snmpv3_priv_pwd": module.params["snmpv3_priv_pwd"], + "snmpv3_queries": module.params["snmpv3_queries"], + "snmpv3_query_port": module.params["snmpv3_query_port"], + "snmpv3_security_level": module.params["snmpv3_security_level"], + "snmpv3_source_ip": module.params["snmpv3_source_ip"], + "snmpv3_status": module.params["snmpv3_status"], + "snmpv3_trap_rport": module.params["snmpv3_trap_rport"], + "snmpv3_trap_status": module.params["snmpv3_trap_status"], + + "syslog_port": module.params["syslog_port"], + "syslog_server": module.params["syslog_server"], + "syslog_mode": module.params["syslog_mode"], + "syslog_status": module.params["syslog_status"], + "syslog_filter": module.params["syslog_filter"], + "syslog_facility": module.params["syslog_facility"], + "syslog_enc_algorithm": module.params["syslog_enc_algorithm"], + "syslog_certificate": module.params["syslog_certificate"], + + "ntp_status": module.params["ntp_status"], + "ntp_sync_interval": module.params["ntp_sync_interval"], + "ntp_type": module.params["ntp_type"], + "ntp_server": module.params["ntp_server"], + "ntp_auth": module.params["ntp_auth"], + "ntp_auth_pwd": module.params["ntp_auth_pwd"], + "ntp_v3": module.params["ntp_v3"], + + "admin_https_redirect": module.params["admin_https_redirect"], + "admin_https_port": module.params["admin_https_port"], + "admin_http_port": module.params["admin_http_port"], + "admin_timeout": module.params["admin_timeout"], + "admin_language": module.params["admin_language"], + "admin_switch_controller": module.params["admin_switch_controller"], + "admin_gui_theme": module.params["admin_gui_theme"], + "admin_enable_fortiguard": module.params["admin_enable_fortiguard"], + "admin_fortianalyzer_target": module.params["admin_fortianalyzer_target"], + "admin_fortiguard_target": module.params["admin_fortiguard_target"], + + "smtp_username": module.params["smtp_username"], + "smtp_password": module.params["smtp_password"], + "smtp_port": module.params["smtp_port"], + "smtp_replyto": module.params["smtp_replyto"], + "smtp_conn_sec": module.params["smtp_conn_sec"], + "smtp_server": module.params["smtp_server"], + "smtp_source_ipv4": module.params["smtp_source_ipv4"], + "smtp_validate_cert": module.params["smtp_validate_cert"], + + "dns_suffix": module.params["dns_suffix"], + "dns_primary_ipv4": module.params["dns_primary_ipv4"], + "dns_secondary_ipv4": module.params["dns_secondary_ipv4"], + "delete_provisioning_template": module.params["delete_provisioning_template"] + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + try: + # CHECK IF WE ARE DELETING AN ENTIRE TEMPLATE. IF THAT'S THE CASE DO IT FIRST AND IGNORE THE REST. + if paramgram["delete_provisioning_template"] is not None: + results = set_devprof(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -10, -1], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram), + stop_on_success=True) + except Exception as err: + raise FMGBaseException(err) + + try: + # CHECK TO SEE IF THE DEVPROF TEMPLATE EXISTS + devprof = get_devprof(fmgr, paramgram) + if devprof[0] != 0: + results = set_devprof(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -2], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS THE SNMP SETTINGS IF THE SNMP_STATUS VARIABLE IS SET + if paramgram["snmp_status"] is not None: + results = set_devprof_snmp(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + # PROCESS THE SNMP V2C COMMUNITY SETTINGS IF THEY ARE ALL HERE + if all(v is not None for v in (paramgram["snmp_v2c_query_port"], paramgram["snmp_v2c_trap_port"], + paramgram["snmp_v2c_status"], paramgram["snmp_v2c_trap_status"], + paramgram["snmp_v2c_query_status"], paramgram["snmp_v2c_name"], + paramgram["snmp_v2c_id"])): + results = set_devprof_snmp_v2c(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -10033], stop_on_success=True, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + # PROCESS THE SNMPV3 USER IF THERE + if all(v is not None for v in ( + [paramgram["snmpv3_auth_proto"], paramgram["snmpv3_auth_pwd"], paramgram["snmpv3_name"], + paramgram["snmpv3_notify_hosts"], paramgram["snmpv3_priv_proto"], + paramgram["snmpv3_priv_pwd"], + paramgram["snmpv3_queries"], + paramgram["snmpv3_query_port"], paramgram["snmpv3_security_level"], + paramgram["snmpv3_source_ip"], + paramgram["snmpv3_status"], paramgram["snmpv3_trap_rport"], paramgram["snmpv3_trap_status"]])): + + results = set_devprof_snmp_v3(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -10033, -10000, -3], + stop_on_success=True, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS THE SYSLOG SETTINGS IF THE ALL THE NEEDED SYSLOG VARIABLES ARE PRESENT + if all(v is not None for v in [paramgram["syslog_port"], paramgram["syslog_mode"], + paramgram["syslog_server"], paramgram["syslog_status"]]): + # enable syslog in the devprof template + results = set_devprof_syslog(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -10033, -10000, -3], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF THE SYSLOG FILTER IS PRESENT THEN RUN THAT + if paramgram["syslog_filter"] is not None: + results = set_devprof_syslog_filter(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS NTP OPTIONS + if paramgram["ntp_status"]: + # VALIDATE INPUT + if paramgram["ntp_type"] == "custom" and paramgram["ntp_server"] is None: + module.exit_json(msg="You requested custom NTP type but did not provide ntp_server parameter.") + if paramgram["ntp_auth"] == "enable" and paramgram["ntp_auth_pwd"] is None: + module.exit_json( + msg="You requested NTP Authentication but did not provide ntp_auth_pwd parameter.") + + results = set_devprof_ntp(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + try: + # PROCESS THE ADMIN OPTIONS + if any(v is not None for v in ( + paramgram["admin_https_redirect"], paramgram["admin_https_port"], paramgram["admin_http_port"], + paramgram["admin_timeout"], + paramgram["admin_language"], paramgram["admin_switch_controller"], + paramgram["admin_gui_theme"])): + + results = set_devprof_admin(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS FORTIGUARD OPTIONS + if paramgram["admin_enable_fortiguard"] is not None: + + results = set_devprof_toggle_fg(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + results = set_devprof_fg(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS THE SMTP OPTIONS + if all(v is not None for v in ( + paramgram["smtp_username"], paramgram["smtp_password"], paramgram["smtp_port"], + paramgram["smtp_replyto"], + paramgram["smtp_conn_sec"], paramgram["smtp_server"], + paramgram["smtp_source_ipv4"], paramgram["smtp_validate_cert"])): + + results = set_devprof_smtp(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS THE DNS OPTIONS + if any(v is not None for v in + (paramgram["dns_suffix"], paramgram["dns_primary_ipv4"], paramgram["dns_secondary_ipv4"])): + results = set_devprof_dns(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS THE admin_fortianalyzer_target OPTIONS + if paramgram["admin_fortianalyzer_target"] is not None: + + results = set_devprof_faz(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # PROCESS THE PROVISIONING TEMPLATE TARGET PARAMETER + if paramgram["provision_targets"] is not None: + if paramgram["mode"] != "delete": + results = set_devprof_scope(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0], stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + if paramgram["mode"] == "delete": + # WE NEED TO FIGURE OUT WHAT'S THERE FIRST, BEFORE WE CAN RUN THIS + targets_to_add = list() + try: + current_scope = get_devprof_scope(fmgr, paramgram) + targets_to_remove = paramgram["provision_targets"].strip().split(",") + targets = current_scope[1][1]["scope member"] + for target in targets: + if target["name"] not in targets_to_remove: + target_append = {"name": target["name"]} + targets_to_add.append(target_append) + except BaseException: + pass + paramgram["targets_to_add"] = targets_to_add + results = set_devprof_scope(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -10033, -10000, -3], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_address.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_address.py new file mode 100644 index 00000000..c060c00d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_address.py @@ -0,0 +1,661 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwobj_address +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Allows the management of firewall objects in FortiManager +description: + - Allows for the management of IPv4, IPv6, and multicast address objects within FortiManager. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + allow_routing: + description: + - Enable/disable use of this address in the static route configuration. + choices: ['enable', 'disable'] + default: 'disable' + + associated_interface: + description: + - Associated interface name. + + cache_ttl: + description: + - Minimal TTL of individual IP addresses in FQDN cache. Only applies when type = wildcard-fqdn. + + color: + description: + - Color of the object in FortiManager GUI. + - Takes integers 1-32 + default: 22 + + comment: + description: + - Comment for the object in FortiManager. + + country: + description: + - Country name. Required if type = geographic. + + end_ip: + description: + - End IP. Only used when ipv4 = iprange. + + group_members: + description: + - Address group member. If this is defined w/out group_name, the operation will fail. + + group_name: + description: + - Address group name. If this is defined in playbook task, all other options are ignored. + + ipv4: + description: + - Type of IPv4 Object. + - Must not be specified with either multicast or IPv6 parameters. + choices: ['ipmask', 'iprange', 'fqdn', 'wildcard', 'geography', 'wildcard-fqdn', 'group'] + + ipv4addr: + description: + - IP and network mask. If only defining one IP use this parameter. (i.e. 10.7.220.30/255.255.255.255) + - Can also define subnets (i.e. 10.7.220.0/255.255.255.0) + - Also accepts CIDR (i.e. 10.7.220.0/24) + - If Netmask is omitted after IP address, /32 is assumed. + - When multicast is set to Broadcast Subnet the ipv4addr parameter is used to specify the subnet. + + ipv6: + description: + - Puts module into IPv6 mode. + - Must not be specified with either ipv4 or multicast parameters. + choices: ['ip', 'iprange', 'group'] + + ipv6addr: + description: + - IPv6 address in full. (i.e. 2001:0db8:85a3:0000:0000:8a2e:0370:7334) + + fqdn: + description: + - Fully qualified domain name. + + mode: + description: + - Sets one of three modes for managing the object. + choices: ['add', 'set', 'delete'] + default: add + + multicast: + description: + - Manages Multicast Address Objects. + - Sets either a Multicast IP Range or a Broadcast Subnet. + - Must not be specified with either ipv4 or ipv6 parameters. + - When set to Broadcast Subnet the ipv4addr parameter is used to specify the subnet. + - Can create IPv4 Multicast Objects (multicastrange and broadcastmask options -- uses start/end-ip and ipv4addr). + choices: ['multicastrange', 'broadcastmask', 'ip6'] + + name: + description: + - Friendly Name Address object name in FortiManager. + + obj_id: + description: + - Object ID for NSX. + + start_ip: + description: + - Start IP. Only used when ipv4 = iprange. + + visibility: + description: + - Enable/disable address visibility. + choices: ['enable', 'disable'] + default: 'enable' + + wildcard: + description: + - IP address and wildcard netmask. Required if ipv4 = wildcard. + + wildcard_fqdn: + description: + - Wildcard FQDN. Required if ipv4 = wildcard-fqdn. +''' + +EXAMPLES = ''' +- name: ADD IPv4 IP ADDRESS OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "ipmask" + ipv4addr: "10.7.220.30/32" + name: "ansible_v4Obj" + comment: "Created by Ansible" + color: "6" + +- name: ADD IPv4 IP ADDRESS OBJECT MORE OPTIONS + community.fortios.fmgr_fwobj_address: + ipv4: "ipmask" + ipv4addr: "10.7.220.34/32" + name: "ansible_v4Obj_MORE" + comment: "Created by Ansible" + color: "6" + allow_routing: "enable" + cache_ttl: "180" + associated_interface: "port1" + obj_id: "123" + +- name: ADD IPv4 IP ADDRESS SUBNET OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "ipmask" + ipv4addr: "10.7.220.0/255.255.255.128" + name: "ansible_subnet" + comment: "Created by Ansible" + mode: "set" + +- name: ADD IPv4 IP ADDRESS RANGE OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "iprange" + start_ip: "10.7.220.1" + end_ip: "10.7.220.125" + name: "ansible_range" + comment: "Created by Ansible" + +- name: ADD IPv4 IP ADDRESS WILDCARD OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "wildcard" + wildcard: "10.7.220.30/255.255.255.255" + name: "ansible_wildcard" + comment: "Created by Ansible" + +- name: ADD IPv4 IP ADDRESS WILDCARD FQDN OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "wildcard-fqdn" + wildcard_fqdn: "*.myds.com" + name: "Synology myds DDNS service" + comment: "Created by Ansible" + +- name: ADD IPv4 IP ADDRESS FQDN OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "fqdn" + fqdn: "ansible.com" + name: "ansible_fqdn" + comment: "Created by Ansible" + +- name: ADD IPv4 IP ADDRESS GEO OBJECT + community.fortios.fmgr_fwobj_address: + ipv4: "geography" + country: "usa" + name: "ansible_geo" + comment: "Created by Ansible" + +- name: ADD IPv6 ADDRESS + community.fortios.fmgr_fwobj_address: + ipv6: "ip" + ipv6addr: "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + name: "ansible_v6Obj" + comment: "Created by Ansible" + +- name: ADD IPv6 ADDRESS RANGE + community.fortios.fmgr_fwobj_address: + ipv6: "iprange" + start_ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334" + end_ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7446" + name: "ansible_v6range" + comment: "Created by Ansible" + +- name: ADD IPv4 IP ADDRESS GROUP + community.fortios.fmgr_fwobj_address: + ipv4: "group" + group_name: "ansibleIPv4Group" + group_members: "ansible_fqdn, ansible_wildcard, ansible_range" + +- name: ADD IPv6 IP ADDRESS GROUP + community.fortios.fmgr_fwobj_address: + ipv6: "group" + group_name: "ansibleIPv6Group" + group_members: "ansible_v6Obj, ansible_v6range" + +- name: ADD MULTICAST RANGE + community.fortios.fmgr_fwobj_address: + multicast: "multicastrange" + start_ip: "224.0.0.251" + end_ip: "224.0.0.251" + name: "ansible_multicastrange" + comment: "Created by Ansible" + +- name: ADD BROADCAST SUBNET + community.fortios.fmgr_fwobj_address: + multicast: "broadcastmask" + ipv4addr: "10.7.220.0/24" + name: "ansible_broadcastSubnet" + comment: "Created by Ansible" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + + +import re +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def fmgr_fwobj_ipv4(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # EVAL THE MODE PARAMETER FOR SET OR ADD + if paramgram["mode"] in ['set', 'add']: + # CREATE THE DATAGRAM DICTIONARY + # ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE + # SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED + datagram = { + "comment": paramgram["comment"], + "associated-interface": paramgram["associated-interface"], + "cache-ttl": paramgram["cache-ttl"], + "name": paramgram["name"], + "allow-routing": paramgram["allow-routing"], + "color": paramgram["color"], + "meta fields": {}, + "dynamic_mapping": [], + "visibility": paramgram["allow-routing"], + "type": paramgram["ipv4"], + } + + # SET THE CORRECT URL BASED ON THE TYPE (WE'RE DOING GROUPS IN THIS METHOD, TOO) + if datagram["type"] == "group": + url = '/pm/config/adom/{adom}/obj/firewall/addrgrp'.format(adom=paramgram["adom"]) + else: + url = '/pm/config/adom/{adom}/obj/firewall/address'.format(adom=paramgram["adom"]) + + ######################### + # IF type = 'ipmask' + ######################### + if datagram["type"] == "ipmask": + # CREATE THE SUBNET LIST OBJECT + subnet = [] + # EVAL THE IPV4ADDR INPUT AND SPLIT THE IP ADDRESS FROM THE MASK AND APPEND THEM TO THE SUBNET LIST + for subnets in paramgram["ipv4addr"].split("/"): + subnet.append(subnets) + + # CHECK THAT THE SECOND ENTRY IN THE SUBNET LIST (WHAT WAS TO THE RIGHT OF THE / CHARACTER) + # IS IN SUBNET MASK FORMAT AND NOT CIDR FORMAT. + # IF IT IS IN CIDR FORMAT, WE NEED TO CONVERT IT TO SUBNET BIT MASK FORMAT FOR THE JSON API + if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]): + # IF THE SUBNET PARAMETER INPUT DIDN'T LOOK LIKE xxx.xxx.xxx.xxx TO REGEX... + # ... RUN IT THROUGH THE CIDR_TO_NETMASK() FUNCTION + mask = fmgr._tools.cidr_to_netmask(subnet[1]) + # AND THEN UPDATE THE SUBNET LIST OBJECT + subnet[1] = mask + + # INCLUDE THE SUBNET LIST OBJECT IN THE DATAGRAM DICTIONARY TO BE SUBMITTED + datagram["subnet"] = subnet + + ######################### + # IF type = 'iprange' + ######################### + if datagram["type"] == "iprange": + datagram["start-ip"] = paramgram["start-ip"] + datagram["end-ip"] = paramgram["end-ip"] + datagram["subnet"] = ["0.0.0.0", "0.0.0.0"] + + ######################### + # IF type = 'geography' + ######################### + if datagram["type"] == "geography": + datagram["country"] = paramgram["country"] + + ######################### + # IF type = 'wildcard' + ######################### + if datagram["type"] == "wildcard": + + subnet = [] + for subnets in paramgram["wildcard"].split("/"): + subnet.append(subnets) + + if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]): + mask = fmgr._tools.cidr_to_netmask(subnet[1]) + subnet[1] = mask + + datagram["wildcard"] = subnet + + ######################### + # IF type = 'wildcard-fqdn' + ######################### + if datagram["type"] == "wildcard-fqdn": + datagram["wildcard-fqdn"] = paramgram["wildcard-fqdn"] + + ######################### + # IF type = 'fqdn' + ######################### + if datagram["type"] == "fqdn": + datagram["fqdn"] = paramgram["fqdn"] + + ######################### + # IF type = 'group' + ######################### + if datagram["type"] == "group": + datagram = { + "comment": paramgram["comment"], + "name": paramgram["group_name"], + "color": paramgram["color"], + "meta fields": {}, + "dynamic_mapping": [], + "visibility": paramgram["visibility"] + } + + members = [] + group_members = paramgram["group_members"].replace(" ", "") + try: + for member in group_members.split(","): + members.append(member) + except Exception: + pass + + datagram["member"] = members + + # EVAL THE MODE PARAMETER FOR DELETE + if paramgram["mode"] == "delete": + # IF A GROUP, SET THE CORRECT NAME AND URL FOR THE GROUP ENDPOINT + if paramgram["ipv4"] == "group": + datagram = {} + url = '/pm/config/adom/{adom}/obj/firewall/addrgrp/{name}'.format(adom=paramgram["adom"], + name=paramgram["group_name"]) + # OTHERWISE WE'RE JUST GOING TO USE THE ADDRESS ENDPOINT + else: + datagram = {} + url = '/pm/config/adom/{adom}/obj/firewall/address/{name}'.format(adom=paramgram["adom"], + name=paramgram["name"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def fmgr_fwobj_ipv6(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # EVAL THE MODE PARAMETER FOR SET OR ADD + if paramgram["mode"] in ['set', 'add']: + # CREATE THE DATAGRAM DICTIONARY + # ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE + # SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED + datagram = { + "comment": paramgram["comment"], + "name": paramgram["name"], + "color": paramgram["color"], + "dynamic_mapping": [], + "visibility": paramgram["visibility"], + "type": paramgram["ipv6"] + } + + # SET THE CORRECT URL BASED ON THE TYPE (WE'RE DOING GROUPS IN THIS METHOD, TOO) + if datagram["type"] == "group": + url = '/pm/config/adom/{adom}/obj/firewall/addrgrp6'.format(adom=paramgram["adom"]) + else: + url = '/pm/config/adom/{adom}/obj/firewall/address6'.format(adom=paramgram["adom"]) + + ######################### + # IF type = 'ip' + ######################### + if datagram["type"] == "ip": + datagram["type"] = "ipprefix" + datagram["ip6"] = paramgram["ipv6addr"] + + ######################### + # IF type = 'iprange' + ######################### + if datagram["type"] == "iprange": + datagram["start-ip"] = paramgram["start-ip"] + datagram["end-ip"] = paramgram["end-ip"] + + ######################### + # IF type = 'group' + ######################### + if datagram["type"] == "group": + datagram = None + datagram = { + "comment": paramgram["comment"], + "name": paramgram["group_name"], + "color": paramgram["color"], + "visibility": paramgram["visibility"] + } + + members = [] + group_members = paramgram["group_members"].replace(" ", "") + try: + for member in group_members.split(","): + members.append(member) + except Exception: + pass + + datagram["member"] = members + + # EVAL THE MODE PARAMETER FOR DELETE + if paramgram["mode"] == "delete": + # IF A GROUP, SET THE CORRECT NAME AND URL FOR THE GROUP ENDPOINT + if paramgram["ipv6"] == "group": + datagram = {} + url = '/pm/config/adom/{adom}/obj/firewall/addrgrp6/{name}'.format(adom=paramgram["adom"], + name=paramgram["group_name"]) + # OTHERWISE WE'RE JUST GOING TO USE THE ADDRESS ENDPOINT + else: + datagram = {} + url = '/pm/config/adom/{adom}/obj/firewall/address6/{name}'.format(adom=paramgram["adom"], + name=paramgram["name"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def fmgr_fwobj_multicast(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # EVAL THE MODE PARAMETER FOR SET OR ADD + if paramgram["mode"] in ['set', 'add']: + # CREATE THE DATAGRAM DICTIONARY + # ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE + # SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED + datagram = { + "associated-interface": paramgram["associated-interface"], + "comment": paramgram["comment"], + "name": paramgram["name"], + "color": paramgram["color"], + "type": paramgram["multicast"], + "visibility": paramgram["visibility"], + } + + # SET THE CORRECT URL + url = '/pm/config/adom/{adom}/obj/firewall/multicast-address'.format(adom=paramgram["adom"]) + + ######################### + # IF type = 'multicastrange' + ######################### + if paramgram["multicast"] == "multicastrange": + datagram["start-ip"] = paramgram["start-ip"] + datagram["end-ip"] = paramgram["end-ip"] + datagram["subnet"] = ["0.0.0.0", "0.0.0.0"] + + ######################### + # IF type = 'broadcastmask' + ######################### + if paramgram["multicast"] == "broadcastmask": + # EVAL THE IPV4ADDR INPUT AND SPLIT THE IP ADDRESS FROM THE MASK AND APPEND THEM TO THE SUBNET LIST + subnet = [] + for subnets in paramgram["ipv4addr"].split("/"): + subnet.append(subnets) + # CHECK THAT THE SECOND ENTRY IN THE SUBNET LIST (WHAT WAS TO THE RIGHT OF THE / CHARACTER) + # IS IN SUBNET MASK FORMAT AND NOT CIDR FORMAT. + # IF IT IS IN CIDR FORMAT, WE NEED TO CONVERT IT TO SUBNET BIT MASK FORMAT FOR THE JSON API + if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]): + # IF THE SUBNET PARAMETER INPUT DIDN'T LOOK LIKE 255.255.255.255 TO REGEX... + # ... RUN IT THROUGH THE fmgr_cidr_to_netmask() FUNCTION + mask = fmgr._tools.cidr_to_netmask(subnet[1]) + # AND THEN UPDATE THE SUBNET LIST OBJECT + subnet[1] = mask + + # INCLUDE THE SUBNET LIST OBJECT IN THE DATAGRAM DICTIONARY TO BE SUBMITTED + datagram["subnet"] = subnet + + # EVAL THE MODE PARAMETER FOR DELETE + if paramgram["mode"] == "delete": + datagram = { + "name": paramgram["name"] + } + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/firewall/multicast-address/{name}'.format(adom=paramgram["adom"], + name=paramgram["name"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "set", "delete"], type="str", default="add"), + + allow_routing=dict(required=False, type="str", choices=['enable', 'disable'], default="disable"), + associated_interface=dict(required=False, type="str"), + cache_ttl=dict(required=False, type="str"), + color=dict(required=False, type="str", default=22), + comment=dict(required=False, type="str"), + country=dict(required=False, type="str"), + fqdn=dict(required=False, type="str"), + name=dict(required=False, type="str"), + start_ip=dict(required=False, type="str"), + end_ip=dict(required=False, type="str"), + ipv4=dict(required=False, type="str", choices=['ipmask', 'iprange', 'fqdn', 'wildcard', + 'geography', 'wildcard-fqdn', 'group']), + visibility=dict(required=False, type="str", choices=['enable', 'disable'], default="enable"), + wildcard=dict(required=False, type="str"), + wildcard_fqdn=dict(required=False, type="str"), + ipv6=dict(required=False, type="str", choices=['ip', 'iprange', 'group']), + group_members=dict(required=False, type="str"), + group_name=dict(required=False, type="str"), + ipv4addr=dict(required=False, type="str"), + ipv6addr=dict(required=False, type="str"), + multicast=dict(required=False, type="str", choices=['multicastrange', 'broadcastmask', 'ip6']), + obj_id=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, + mutually_exclusive=[ + ['ipv4', 'ipv6'], + ['ipv4', 'multicast'], + ['ipv6', 'multicast'] + ]) + paramgram = { + "adom": module.params["adom"], + "allow-routing": module.params["allow_routing"], + "associated-interface": module.params["associated_interface"], + "cache-ttl": module.params["cache_ttl"], + "color": module.params["color"], + "comment": module.params["comment"], + "country": module.params["country"], + "end-ip": module.params["end_ip"], + "fqdn": module.params["fqdn"], + "name": module.params["name"], + "start-ip": module.params["start_ip"], + "visibility": module.params["visibility"], + "wildcard": module.params["wildcard"], + "wildcard-fqdn": module.params["wildcard_fqdn"], + "ipv6": module.params["ipv6"], + "ipv4": module.params["ipv4"], + "group_members": module.params["group_members"], + "group_name": module.params["group_name"], + "ipv4addr": module.params["ipv4addr"], + "ipv6addr": module.params["ipv6addr"], + "multicast": module.params["multicast"], + "mode": module.params["mode"], + "obj-id": module.params["obj_id"], + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr._tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + try: + if paramgram["ipv4"]: + results = fmgr_fwobj_ipv4(fmgr, paramgram) + + elif paramgram["ipv6"]: + results = fmgr_fwobj_ipv6(fmgr, paramgram) + + elif paramgram["multicast"]: + results = fmgr_fwobj_multicast(fmgr, paramgram) + + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + if results is not None: + return module.exit_json(**results[1]) + else: + return module.exit_json(msg="Couldn't find a proper ipv4 or ipv6 or multicast parameter " + "to run in the logic tree. Exiting...") + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_ippool.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_ippool.py new file mode 100644 index 00000000..a0b39ab1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_ippool.py @@ -0,0 +1,442 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwobj_ippool +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Allows the editing of IP Pool Objects within FortiManager. +description: + - Allows users to add/edit/delete IP Pool Objects. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + type: + description: + - IP pool type (overload, one-to-one, fixed port range, or port block allocation). + - choice | overload | IP addresses in the IP pool can be shared by clients. + - choice | one-to-one | One to one mapping. + - choice | fixed-port-range | Fixed port range. + - choice | port-block-allocation | Port block allocation. + required: false + choices: ["overload", "one-to-one", "fixed-port-range", "port-block-allocation"] + + startip: + description: + - First IPv4 address (inclusive) in the range for the address pool (format xxx.xxx.xxx.xxx, Default| 0.0.0.0). + required: false + + source_startip: + description: + - First IPv4 address (inclusive) in the range of the source addresses to be translated (format xxx.xxx.xxx.xxx, + Default| 0.0.0.0). + required: false + + source_endip: + description: + - Final IPv4 address (inclusive) in the range of the source addresses to be translated (format xxx.xxx.xxx.xxx, + Default| 0.0.0.0). + required: false + + permit_any_host: + description: + - Enable/disable full cone NAT. + - choice | disable | Disable full cone NAT. + - choice | enable | Enable full cone NAT. + required: false + choices: ["disable", "enable"] + + pba_timeout: + description: + - Port block allocation timeout (seconds). + required: false + + num_blocks_per_user: + description: + - Number of addresses blocks that can be used by a user (1 to 128, default = 8). + required: false + + name: + description: + - IP pool name. + required: false + + endip: + description: + - Final IPv4 address (inclusive) in the range for the address pool (format xxx.xxx.xxx.xxx, Default| 0.0.0.0). + required: false + + comments: + description: + - Comment. + required: false + + block_size: + description: + - Number of addresses in a block (64 to 4096, default = 128). + required: false + + associated_interface: + description: + - Associated interface name. + required: false + + arp_reply: + description: + - Enable/disable replying to ARP requests when an IP Pool is added to a policy (default = enable). + - choice | disable | Disable ARP reply. + - choice | enable | Enable ARP reply. + required: false + choices: ["disable", "enable"] + + arp_intf: + description: + - Select an interface from available options that will reply to ARP requests. (If blank, any is selected). + required: false + + dynamic_mapping: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameter.ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + dynamic_mapping_arp_intf: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_arp_reply: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + choices: ["disable", "enable"] + + dynamic_mapping_associated_interface: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_block_size: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_comments: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_endip: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_num_blocks_per_user: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_pba_timeout: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_permit_any_host: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + choices: ["disable", "enable"] + + dynamic_mapping_source_endip: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_source_startip: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_startip: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_type: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + choices: ["overload", "one-to-one", "fixed-port-range", "port-block-allocation"] + + +''' + +EXAMPLES = ''' +- name: ADD FMGR_FIREWALL_IPPOOL Overload + community.fortios.fmgr_fwobj_ippool: + mode: "add" + adom: "ansible" + name: "Ansible_pool4_overload" + comments: "Created by ansible" + type: "overload" + + # OPTIONS FOR ALL MODES + startip: "10.10.10.10" + endip: "10.10.10.100" + arp_reply: "enable" + +- name: ADD FMGR_FIREWALL_IPPOOL one-to-one + community.fortios.fmgr_fwobj_ippool: + mode: "add" + adom: "ansible" + name: "Ansible_pool4_121" + comments: "Created by ansible" + type: "one-to-one" + + # OPTIONS FOR ALL MODES + startip: "10.10.20.10" + endip: "10.10.20.100" + arp_reply: "enable" + +- name: ADD FMGR_FIREWALL_IPPOOL FIXED PORT RANGE + community.fortios.fmgr_fwobj_ippool: + mode: "add" + adom: "ansible" + name: "Ansible_pool4_fixed_port" + comments: "Created by ansible" + type: "fixed-port-range" + + # OPTIONS FOR ALL MODES + startip: "10.10.40.10" + endip: "10.10.40.100" + arp_reply: "enable" + # FIXED PORT RANGE OPTIONS + source_startip: "192.168.20.1" + source_endip: "192.168.20.20" + +- name: ADD FMGR_FIREWALL_IPPOOL PORT BLOCK ALLOCATION + community.fortios.fmgr_fwobj_ippool: + mode: "add" + adom: "ansible" + name: "Ansible_pool4_port_block_allocation" + comments: "Created by ansible" + type: "port-block-allocation" + + # OPTIONS FOR ALL MODES + startip: "10.10.30.10" + endip: "10.10.30.100" + arp_reply: "enable" + # PORT BLOCK ALLOCATION OPTIONS + block_size: "128" + num_blocks_per_user: "1" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_fwobj_ippool_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/firewall/ippool'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/firewall/ippool/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + type=dict(required=False, type="str", choices=["overload", + "one-to-one", + "fixed-port-range", + "port-block-allocation"]), + startip=dict(required=False, type="str"), + source_startip=dict(required=False, type="str"), + source_endip=dict(required=False, type="str"), + permit_any_host=dict(required=False, type="str", choices=["disable", "enable"]), + pba_timeout=dict(required=False, type="int"), + num_blocks_per_user=dict(required=False, type="int"), + name=dict(required=False, type="str"), + endip=dict(required=False, type="str"), + comments=dict(required=False, type="str"), + block_size=dict(required=False, type="int"), + associated_interface=dict(required=False, type="str"), + arp_reply=dict(required=False, type="str", choices=["disable", "enable"]), + arp_intf=dict(required=False, type="str"), + dynamic_mapping=dict(required=False, type="list"), + dynamic_mapping_arp_intf=dict(required=False, type="str"), + dynamic_mapping_arp_reply=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_associated_interface=dict(required=False, type="str"), + dynamic_mapping_block_size=dict(required=False, type="int"), + dynamic_mapping_comments=dict(required=False, type="str"), + dynamic_mapping_endip=dict(required=False, type="str"), + dynamic_mapping_num_blocks_per_user=dict(required=False, type="int"), + dynamic_mapping_pba_timeout=dict(required=False, type="int"), + dynamic_mapping_permit_any_host=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_source_endip=dict(required=False, type="str"), + dynamic_mapping_source_startip=dict(required=False, type="str"), + dynamic_mapping_startip=dict(required=False, type="str"), + dynamic_mapping_type=dict(required=False, type="str", choices=["overload", + "one-to-one", + "fixed-port-range", + "port-block-allocation"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "type": module.params["type"], + "startip": module.params["startip"], + "source-startip": module.params["source_startip"], + "source-endip": module.params["source_endip"], + "permit-any-host": module.params["permit_any_host"], + "pba-timeout": module.params["pba_timeout"], + "num-blocks-per-user": module.params["num_blocks_per_user"], + "name": module.params["name"], + "endip": module.params["endip"], + "comments": module.params["comments"], + "block-size": module.params["block_size"], + "associated-interface": module.params["associated_interface"], + "arp-reply": module.params["arp_reply"], + "arp-intf": module.params["arp_intf"], + "dynamic_mapping": { + "arp-intf": module.params["dynamic_mapping_arp_intf"], + "arp-reply": module.params["dynamic_mapping_arp_reply"], + "associated-interface": module.params["dynamic_mapping_associated_interface"], + "block-size": module.params["dynamic_mapping_block_size"], + "comments": module.params["dynamic_mapping_comments"], + "endip": module.params["dynamic_mapping_endip"], + "num-blocks-per-user": module.params["dynamic_mapping_num_blocks_per_user"], + "pba-timeout": module.params["dynamic_mapping_pba_timeout"], + "permit-any-host": module.params["dynamic_mapping_permit_any_host"], + "source-endip": module.params["dynamic_mapping_source_endip"], + "source-startip": module.params["dynamic_mapping_source_startip"], + "startip": module.params["dynamic_mapping_startip"], + "type": module.params["dynamic_mapping_type"], + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['dynamic_mapping'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + # UPDATE THE CHANGED PARAMGRAM + module.paramgram = paramgram + + results = DEFAULT_RESULT_OBJ + try: + results = fmgr_fwobj_ippool_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_ippool6.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_ippool6.py new file mode 100644 index 00000000..15e8977f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_ippool6.py @@ -0,0 +1,223 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwobj_ippool6 +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Allows the editing of IP Pool Objects within FortiManager. +description: + - Allows users to add/edit/delete IPv6 Pool Objects. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + startip: + description: + - First IPv6 address (inclusive) in the range for the address pool. + required: false + + name: + description: + - IPv6 IP pool name. + required: false + + endip: + description: + - Final IPv6 address (inclusive) in the range for the address pool. + required: false + + comments: + description: + - Comment. + required: false + + dynamic_mapping: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + dynamic_mapping_comments: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_endip: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + dynamic_mapping_startip: + description: + - Dynamic Mapping clone of original suffixed parameter. + required: false + + +''' + +EXAMPLES = ''' +- name: ADD FMGR_FIREWALL_IPPOOL6 + fmgr_firewall_ippool6: + mode: "add" + adom: "ansible" + startip: + name: "IPv6 IPPool" + endip: + comments: "Created by Ansible" + +- name: DELETE FMGR_FIREWALL_IPPOOL6 + fmgr_firewall_ippool6: + mode: "delete" + adom: "ansible" + name: "IPv6 IPPool" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +def fmgr_fwobj_ippool6_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/firewall/ippool6'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/firewall/ippool6/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + startip=dict(required=False, type="str"), + name=dict(required=False, type="str"), + endip=dict(required=False, type="str"), + comments=dict(required=False, type="str"), + dynamic_mapping=dict(required=False, type="list"), + dynamic_mapping_comments=dict(required=False, type="str"), + dynamic_mapping_endip=dict(required=False, type="str"), + dynamic_mapping_startip=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "startip": module.params["startip"], + "name": module.params["name"], + "endip": module.params["endip"], + "comments": module.params["comments"], + "dynamic_mapping": { + "comments": module.params["dynamic_mapping_comments"], + "endip": module.params["dynamic_mapping_endip"], + "startip": module.params["dynamic_mapping_startip"], + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['dynamic_mapping'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + + try: + results = fmgr_fwobj_ippool6_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_service.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_service.py new file mode 100644 index 00000000..fb8a3597 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_service.py @@ -0,0 +1,617 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwobj_service +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manages FortiManager Firewall Service Objects. +description: + - Manages FortiManager Firewall Service Objects. + +options: + adom: + description: + -The ADOM the configuration should belong to. + required: false + default: root + + app_category: + description: + - Application category ID. + required: false + + app_service_type: + description: + - Application service type. + required: false + + application: + description: + - Application ID. + required: false + + category: + description: + - Service category. + required: false + + check_reset_range: + description: + - Enable disable RST check. + required: false + + color: + description: + - GUI icon color. + required: false + default: 22 + + comment: + description: + - Comment. + required: false + + custom_type: + description: + - Tells module what kind of custom service to be added. + choices: ['tcp_udp_sctp', 'icmp', 'icmp6', 'ip', 'http', 'ftp', 'connect', 'socks_tcp', 'socks_udp', 'all'] + default: all + required: false + + explicit_proxy: + description: + - Enable/disable explicit web proxy service. + choices: ['enable', 'disable'] + default: 'disable' + required: false + + fqdn: + description: + - Fully qualified domain name. + required: false + default: "" + + group_name: + description: + - Name of the Service Group. + required: false + + group_member: + description: + - Comma-Seperated list of members' names. + required: false + + icmp_code: + description: + - ICMP code. + required: false + + icmp_type: + description: + - ICMP type. + required: false + + iprange: + description: + - Start IP-End IP. + required: false + default: "0.0.0.0" + + name: + description: + - Custom service name. + required: false + + mode: + description: + - Sets one of three modes for managing the object. + choices: ['add', 'set', 'delete'] + default: add + required: false + + object_type: + description: + - Tells module if we are adding a custom service, category, or group. + choices: ['custom', 'group', 'category'] + required: false + + protocol: + description: + - Protocol type. + required: false + + protocol_number: + description: + - IP protocol number. + required: false + + sctp_portrange: + description: + - Multiple SCTP port ranges. Comma separated list of destination ports to add (i.e. '443,80'). + - Syntax is <destPort:sourcePort> + - If no sourcePort is defined, it assumes all of them. + - Ranges can be defined with a hyphen - + - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000). + - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000'). + required: false + + session_ttl: + description: + - Session TTL (300 - 604800, 0 = default). + required: false + default: 0 + + tcp_halfclose_timer: + description: + - TCP half close timeout (1 - 86400 sec, 0 = default). + required: false + default: 0 + + tcp_halfopen_timer: + description: + - TCP half close timeout (1 - 86400 sec, 0 = default). + required: false + default: 0 + + tcp_portrange: + description: + - Comma separated list of destination ports to add (i.e. '443,80'). + - Syntax is <destPort:sourcePort> + - If no sourcePort is defined, it assumes all of them. + - Ranges can be defined with a hyphen - + - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000). + - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000'). + required: false + + tcp_timewait_timer: + description: + - TCP half close timeout (1 - 300 sec, 0 = default). + required: false + default: 0 + + udp_idle_timer: + description: + - TCP half close timeout (0 - 86400 sec, 0 = default). + required: false + default: 0 + + udp_portrange: + description: + - Comma separated list of destination ports to add (i.e. '443,80'). + - Syntax is <destPort:sourcePort> + - If no sourcePort is defined, it assumes all of them. + - Ranges can be defined with a hyphen - + - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000). + - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000'). + required: false + + visibility: + description: + - Enable/disable service visibility. + required: false + choices: ["enable", "disable"] + default: "enable" + +''' + +EXAMPLES = ''' +- name: ADD A CUSTOM SERVICE FOR TCP/UDP/SCP + community.fortios.fmgr_fwobj_service: + adom: "ansible" + name: "ansible_custom_service" + object_type: "custom" + custom_type: "tcp_udp_sctp" + tcp_portrange: "443" + udp_portrange: "51" + sctp_portrange: "100" + +- name: ADD A CUSTOM SERVICE FOR TCP/UDP/SCP WITH SOURCE RANGES AND MULTIPLES + community.fortios.fmgr_fwobj_service: + adom: "ansible" + name: "ansible_custom_serviceWithSource" + object_type: "custom" + custom_type: "tcp_udp_sctp" + tcp_portrange: "443:2000-1000,80-82:10000-20000" + udp_portrange: "51:100-200,162:200-400" + sctp_portrange: "100:2000-2500" + +- name: ADD A CUSTOM SERVICE FOR ICMP + community.fortios.fmgr_fwobj_service: + adom: "ansible" + name: "ansible_custom_icmp" + object_type: "custom" + custom_type: "icmp" + icmp_type: "8" + icmp_code: "3" + +- name: ADD A CUSTOM SERVICE FOR ICMP6 + community.fortios.fmgr_fwobj_service: + adom: "ansible" + name: "ansible_custom_icmp6" + object_type: "custom" + custom_type: "icmp6" + icmp_type: "5" + icmp_code: "1" + +- name: ADD A CUSTOM SERVICE FOR IP - GRE + community.fortios.fmgr_fwobj_service: + adom: "ansible" + name: "ansible_custom_icmp6" + object_type: "custom" + custom_type: "ip" + protocol_number: "47" + +- name: ADD A CUSTOM PROXY FOR ALL WITH SOURCE RANGES AND MULTIPLES + community.fortios.fmgr_fwobj_service: + adom: "ansible" + name: "ansible_custom_proxy_all" + object_type: "custom" + custom_type: "all" + explicit_proxy: "enable" + tcp_portrange: "443:2000-1000,80-82:10000-20000" + iprange: "www.ansible.com" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +def fmgr_fwobj_service_custom(fmgr, paramgram): + """ + description: + - the tcp and udp-portrange parameters are in a list when there are multiple. they are not in a list when they + singular or by themselves (only 1 was listed) + - the syntax for this is (destPort:sourcePort). Ranges are (xxxx-xxxx) i.e. 443:443, or 443:1000-2000. + - if you leave out the second field after the colon (source port) it assumes any source port (which is usual) + - multiples would look like ['443:1000-2000','80'] + - a single would look simple like "443:1000-2000" without the list around it ( a string!) + - the protocol parameter is the protocol NUMBER, not the string of it. + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add']: + # SET THE URL FOR ADD / SET + url = '/pm/config/adom/{adom}/obj/firewall/service/custom'.format(adom=paramgram["adom"]) + # BUILD THE DEFAULT DATAGRAM + datagram = { + # ADVANCED OPTIONS + "app-category": paramgram["app-category"], + "app-service-type": paramgram["app-service-type"], + "application": paramgram["application"], + "category": paramgram["category"], + "check-reset-range": paramgram["check-reset-range"], + "color": paramgram["color"], + "session-ttl": paramgram["session-ttl"], + "tcp-halfclose-timer": paramgram["tcp-halfclose-timer"], + "tcp-halfopen-timer": paramgram["tcp-halfopen-timer"], + "tcp-timewait-timer": paramgram["tcp-timewait-timer"], + "udp-idle-timer": paramgram["udp-idle-timer"], + "visibility": paramgram["visibility"], + "comment": paramgram["comment"], + "proxy": paramgram["explicit-proxy"], + "name": paramgram["name"] + } + + if datagram["proxy"] == "disable": + ####################################### + # object-type = "TCP/UDP/SCTP" + ####################################### + if paramgram["custom_type"] == "tcp_udp_sctp": + datagram["protocol"] = "TCP/UDP/SCTP" + # PROCESS PORT RANGES TO PUT INTO THE PROPER SYNTAX + if paramgram["tcp-portrange"] is not None: + tcp_list = [] + for tcp in paramgram["tcp-portrange"].split(","): + tcp = tcp.strip() + tcp_list.append(tcp) + datagram["tcp-portrange"] = tcp_list + + if paramgram["udp-portrange"] is not None: + udp_list = [] + for udp in paramgram["udp-portrange"].split(","): + udp = udp.strip() + udp_list.append(udp) + datagram["udp-portrange"] = udp_list + + if paramgram["sctp-portrange"] is not None: + sctp_list = [] + for sctp in paramgram["sctp-portrange"].split(","): + sctp = sctp.strip() + sctp_list.append(sctp) + datagram["sctp-portrange"] = sctp_list + + ####################################### + # object-type = "ICMP" + ####################################### + if paramgram["custom_type"] == "icmp": + datagram["icmpcode"] = paramgram["icmp_code"] + datagram["icmptype"] = paramgram["icmp_type"] + datagram["protocol"] = "ICMP" + + ####################################### + # object-type = "ICMP6" + ####################################### + if paramgram["custom_type"] == "icmp6": + datagram["icmpcode"] = paramgram["icmp_code"] + datagram["icmptype"] = paramgram["icmp_type"] + datagram["protocol"] = "ICMP6" + + ####################################### + # object-type = "IP" + ####################################### + if paramgram["custom_type"] == "ip": + datagram["protocol"] = "IP" + datagram["protocol-number"] = paramgram["protocol-number"] + + ####################################### + # object-type in any of the explicit proxy options + ####################################### + if datagram["proxy"] == "enable": + datagram["protocol"] = paramgram["custom_type"].upper() + datagram["iprange"] = paramgram["iprange"] + + # PROCESS PROXY TCP PORT RANGES TO PUT INTO THE PROPER SYNTAX + if paramgram["tcp-portrange"] is not None: + tcp_list = [] + for tcp in paramgram["tcp-portrange"].split(","): + tcp = tcp.strip() + tcp_list.append(tcp) + datagram["tcp-portrange"] = tcp_list + + if paramgram["mode"] == "delete": + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/config/adom/{adom}/obj/firewall/service/custom' \ + '/{name}'.format(adom=paramgram["adom"], name=paramgram["name"]) + + datagram = scrub_dict(datagram) + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def fmgr_fwobj_service_group(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add']: + url = '/pm/config/adom/{adom}/obj/firewall/service/group'.format(adom=paramgram["adom"]) + datagram = { + "name": paramgram["group-name"], + "comment": paramgram["comment"], + "proxy": paramgram["explicit-proxy"], + "color": paramgram["color"] + } + + members = paramgram["group-member"] + member = [] + for obj in members.split(","): + member.append(obj.strip()) + datagram["member"] = member + + if paramgram["mode"] == "delete": + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/config/adom/{adom}/obj/firewall/service/group' \ + '/{name}'.format(adom=paramgram["adom"], name=paramgram["group-name"]) + + datagram = scrub_dict(datagram) + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def fmgr_fwobj_service_category(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + response = DEFAULT_RESULT_OBJ + if paramgram["mode"] in ['set', 'add']: + url = '/pm/config/adom/{adom}/obj/firewall/service/category'.format(adom=paramgram["adom"]) + # GET RID OF ANY WHITESPACE + category = paramgram["category"] + category = category.strip() + + datagram = { + "name": paramgram["category"], + "comment": "Created by Ansible" + } + + # IF MODE = DELETE + if paramgram["mode"] == "delete": + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/config/adom/{adom}/obj/firewall/service/category' \ + '/{name}'.format(adom=paramgram["adom"], name=paramgram["category"]) + + datagram = scrub_dict(datagram) + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + mode=dict(required=False, type="str", choices=['add', 'set', 'delete'], default="add"), + app_category=dict(required=False, type="str"), + app_service_type=dict(required=False, type="str"), + application=dict(required=False, type="str"), + category=dict(required=False, type="str"), + check_reset_range=dict(required=False, type="str"), + color=dict(required=False, type="int", default=22), + comment=dict(required=False, type="str"), + custom_type=dict(required=False, type="str", choices=['tcp_udp_sctp', 'icmp', 'icmp6', 'ip', 'http', 'ftp', + 'connect', 'socks_tcp', 'socks_udp', 'all'], + default="all"), + explicit_proxy=dict(required=False, type="str", choices=['enable', 'disable'], default="disable"), + fqdn=dict(required=False, type="str", default=""), + group_name=dict(required=False, type="str"), + group_member=dict(required=False, type="str"), + icmp_code=dict(required=False, type="int"), + icmp_type=dict(required=False, type="int"), + iprange=dict(required=False, type="str", default="0.0.0.0"), + name=dict(required=False, type="str"), + protocol=dict(required=False, type="str"), + protocol_number=dict(required=False, type="int"), + sctp_portrange=dict(required=False, type="str"), + session_ttl=dict(required=False, type="int", default=0), + object_type=dict(required=False, type="str", choices=['custom', 'group', 'category']), + tcp_halfclose_timer=dict(required=False, type="int", default=0), + tcp_halfopen_timer=dict(required=False, type="int", default=0), + tcp_portrange=dict(required=False, type="str"), + tcp_timewait_timer=dict(required=False, type="int", default=0), + udp_idle_timer=dict(required=False, type="int", default=0), + udp_portrange=dict(required=False, type="str"), + visibility=dict(required=False, type="str", default="enable", choices=["enable", "disable"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE DATAGRAM + paramgram = { + "adom": module.params["adom"], + "app-category": module.params["app_category"], + "app-service-type": module.params["app_service_type"], + "application": module.params["application"], + "category": module.params["category"], + "check-reset-range": module.params["check_reset_range"], + "color": module.params["color"], + "comment": module.params["comment"], + "custom_type": module.params["custom_type"], + "explicit-proxy": module.params["explicit_proxy"], + "fqdn": module.params["fqdn"], + "group-name": module.params["group_name"], + "group-member": module.params["group_member"], + "icmp_code": module.params["icmp_code"], + "icmp_type": module.params["icmp_type"], + "iprange": module.params["iprange"], + "name": module.params["name"], + "mode": module.params["mode"], + "protocol": module.params["protocol"], + "protocol-number": module.params["protocol_number"], + "sctp-portrange": module.params["sctp_portrange"], + "object_type": module.params["object_type"], + "session-ttl": module.params["session_ttl"], + "tcp-halfclose-timer": module.params["tcp_halfclose_timer"], + "tcp-halfopen-timer": module.params["tcp_halfopen_timer"], + "tcp-portrange": module.params["tcp_portrange"], + "tcp-timewait-timer": module.params["tcp_timewait_timer"], + "udp-idle-timer": module.params["udp_idle_timer"], + "udp-portrange": module.params["udp_portrange"], + "visibility": module.params["visibility"], + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + + try: + # CHECK FOR CATEGORIES TO ADD + # THIS IS ONLY WHEN OBJECT_TYPE ISN'T SPECIFICALLY ADDING A CATEGORY! + # WE NEED TO ADD THE CATEGORY BEFORE ADDING THE OBJECT + # IF ANY category ARE DEFINED AND MODE IS ADD OR SET LETS ADD THOSE + # THIS IS A "BLIND ADD" AND THE EXIT CODE FOR OBJECT ALREADY EXISTS IS TREATED AS A PASS + if paramgram["category"] is not None and paramgram["mode"] in ['add', 'set'] \ + and paramgram["object_type"] != "category": + category_add = fmgr_fwobj_service_category(fmgr, paramgram) + fmgr.govern_response(module=module, results=category_add, + ansible_facts=fmgr.construct_ansible_facts(category_add, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF OBJECT_TYPE IS CATEGORY... + if paramgram["object_type"] == 'category': + results = fmgr_fwobj_service_category(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF OBJECT_TYPE IS CUSTOM... + if paramgram["object_type"] == 'custom': + results = fmgr_fwobj_service_custom(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF OBJECT_TYPE IS GROUP... + if paramgram["object_type"] == 'group': + results = fmgr_fwobj_service_group(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_vip.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_vip.py new file mode 100644 index 00000000..adba2e49 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwobj_vip.py @@ -0,0 +1,2424 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwobj_vip +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manages Virtual IPs objects in FortiManager +description: + - Manages Virtual IP objects in FortiManager for IPv4 + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + websphere_server: + description: + - Enable to add an HTTP header to indicate SSL offloading for a WebSphere server. + - choice | disable | Do not add HTTP header indicating SSL offload for WebSphere server. + - choice | enable | Add HTTP header indicating SSL offload for WebSphere server. + required: false + choices: ["disable", "enable"] + + weblogic_server: + description: + - Enable to add an HTTP header to indicate SSL offloading for a WebLogic server. + - choice | disable | Do not add HTTP header indicating SSL offload for WebLogic server. + - choice | enable | Add HTTP header indicating SSL offload for WebLogic server. + required: false + choices: ["disable", "enable"] + + type: + description: + - Configure a static NAT, load balance, server load balance, DNS translation, or FQDN VIP. + - choice | static-nat | Static NAT. + - choice | load-balance | Load balance. + - choice | server-load-balance | Server load balance. + - choice | dns-translation | DNS translation. + - choice | fqdn | FQDN Translation + required: false + choices: ["static-nat", "load-balance", "server-load-balance", "dns-translation", "fqdn"] + + ssl_server_session_state_type: + description: + - How to expire SSL sessions for the segment of the SSL connection between the server and the FortiGate. + - choice | disable | Do not keep session states. + - choice | time | Expire session states after this many minutes. + - choice | count | Expire session states when this maximum is reached. + - choice | both | Expire session states based on time or count, whichever occurs first. + required: false + choices: ["disable", "time", "count", "both"] + + ssl_server_session_state_timeout: + description: + - Number of minutes to keep FortiGate to Server SSL session state. + required: false + + ssl_server_session_state_max: + description: + - Maximum number of FortiGate to Server SSL session states to keep. + required: false + + ssl_server_min_version: + description: + - Lowest SSL/TLS version acceptable from a server. Use the client setting by default. + - choice | ssl-3.0 | SSL 3.0. + - choice | tls-1.0 | TLS 1.0. + - choice | tls-1.1 | TLS 1.1. + - choice | tls-1.2 | TLS 1.2. + - choice | client | Use same value as client configuration. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"] + + ssl_server_max_version: + description: + - Highest SSL/TLS version acceptable from a server. Use the client setting by default. + - choice | ssl-3.0 | SSL 3.0. + - choice | tls-1.0 | TLS 1.0. + - choice | tls-1.1 | TLS 1.1. + - choice | tls-1.2 | TLS 1.2. + - choice | client | Use same value as client configuration. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"] + + ssl_server_algorithm: + description: + - Permitted encryption algorithms for the server side of SSL full mode sessions according to encryption strength + - choice | high | High encryption. Allow only AES and ChaCha. + - choice | low | Low encryption. Allow AES, ChaCha, 3DES, RC4, and DES. + - choice | medium | Medium encryption. Allow AES, ChaCha, 3DES, and RC4. + - choice | custom | Custom encryption. Use ssl-server-cipher-suites to select the cipher suites that are allowed. + - choice | client | Use the same encryption algorithms for both client and server sessions. + required: false + choices: ["high", "low", "medium", "custom", "client"] + + ssl_send_empty_frags: + description: + - Enable/disable sending empty fragments to avoid CBC IV attacks (SSL 3.0 & TLS 1.0 only). + - choice | disable | Do not send empty fragments. + - choice | enable | Send empty fragments. + required: false + choices: ["disable", "enable"] + + ssl_pfs: + description: + - Select the cipher suites that can be used for SSL perfect forward secrecy (PFS). + - choice | require | Allow only Diffie-Hellman cipher-suites, so PFS is applied. + - choice | deny | Allow only non-Diffie-Hellman cipher-suites, so PFS is not applied. + - choice | allow | Allow use of any cipher suite so PFS may or may not be used depending on the cipher suite + required: false + choices: ["require", "deny", "allow"] + + ssl_mode: + description: + - Apply SSL offloading mode + - choice | half | Client to FortiGate SSL. + - choice | full | Client to FortiGate and FortiGate to Server SSL. + required: false + choices: ["half", "full"] + + ssl_min_version: + description: + - Lowest SSL/TLS version acceptable from a client. + - choice | ssl-3.0 | SSL 3.0. + - choice | tls-1.0 | TLS 1.0. + - choice | tls-1.1 | TLS 1.1. + - choice | tls-1.2 | TLS 1.2. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + ssl_max_version: + description: + - Highest SSL/TLS version acceptable from a client. + - choice | ssl-3.0 | SSL 3.0. + - choice | tls-1.0 | TLS 1.0. + - choice | tls-1.1 | TLS 1.1. + - choice | tls-1.2 | TLS 1.2. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + ssl_http_match_host: + description: + - Enable/disable HTTP host matching for location conversion. + - choice | disable | Do not match HTTP host. + - choice | enable | Match HTTP host in response header. + required: false + choices: ["disable", "enable"] + + ssl_http_location_conversion: + description: + - Enable to replace HTTP with HTTPS in the reply's Location HTTP header field. + - choice | disable | Disable HTTP location conversion. + - choice | enable | Enable HTTP location conversion. + required: false + choices: ["disable", "enable"] + + ssl_hsts_include_subdomains: + description: + - Indicate that HSTS header applies to all subdomains. + - choice | disable | HSTS header does not apply to subdomains. + - choice | enable | HSTS header applies to subdomains. + required: false + choices: ["disable", "enable"] + + ssl_hsts_age: + description: + - Number of seconds the client should honour the HSTS setting. + required: false + + ssl_hsts: + description: + - Enable/disable including HSTS header in response. + - choice | disable | Do not add a HSTS header to each a HTTP response. + - choice | enable | Add a HSTS header to each HTTP response. + required: false + choices: ["disable", "enable"] + + ssl_hpkp_report_uri: + description: + - URL to report HPKP violations to. + required: false + + ssl_hpkp_primary: + description: + - Certificate to generate primary HPKP pin from. + required: false + + ssl_hpkp_include_subdomains: + description: + - Indicate that HPKP header applies to all subdomains. + - choice | disable | HPKP header does not apply to subdomains. + - choice | enable | HPKP header applies to subdomains. + required: false + choices: ["disable", "enable"] + + ssl_hpkp_backup: + description: + - Certificate to generate backup HPKP pin from. + required: false + + ssl_hpkp_age: + description: + - Number of seconds the client should honour the HPKP setting. + required: false + + ssl_hpkp: + description: + - Enable/disable including HPKP header in response. + - choice | disable | Do not add a HPKP header to each HTTP response. + - choice | enable | Add a HPKP header to each a HTTP response. + - choice | report-only | Add a HPKP Report-Only header to each HTTP response. + required: false + choices: ["disable", "enable", "report-only"] + + ssl_dh_bits: + description: + - Number of bits to use in the Diffie-Hellman exchange for RSA encryption of SSL sessions. + - choice | 768 | 768-bit Diffie-Hellman prime. + - choice | 1024 | 1024-bit Diffie-Hellman prime. + - choice | 1536 | 1536-bit Diffie-Hellman prime. + - choice | 2048 | 2048-bit Diffie-Hellman prime. + - choice | 3072 | 3072-bit Diffie-Hellman prime. + - choice | 4096 | 4096-bit Diffie-Hellman prime. + required: false + choices: ["768", "1024", "1536", "2048", "3072", "4096"] + + ssl_client_session_state_type: + description: + - How to expire SSL sessions for the segment of the SSL connection between the client and the FortiGate. + - choice | disable | Do not keep session states. + - choice | time | Expire session states after this many minutes. + - choice | count | Expire session states when this maximum is reached. + - choice | both | Expire session states based on time or count, whichever occurs first. + required: false + choices: ["disable", "time", "count", "both"] + + ssl_client_session_state_timeout: + description: + - Number of minutes to keep client to FortiGate SSL session state. + required: false + + ssl_client_session_state_max: + description: + - Maximum number of client to FortiGate SSL session states to keep. + required: false + + ssl_client_renegotiation: + description: + - Allow, deny, or require secure renegotiation of client sessions to comply with RFC 5746. + - choice | deny | Abort any client initiated SSL re-negotiation attempt. + - choice | allow | Allow a SSL client to renegotiate. + - choice | secure | Abort any client initiated SSL re-negotiation attempt that does not use RFC 5746. + required: false + choices: ["deny", "allow", "secure"] + + ssl_client_fallback: + description: + - Enable/disable support for preventing Downgrade Attacks on client connections (RFC 7507). + - choice | disable | Disable. + - choice | enable | Enable. + required: false + choices: ["disable", "enable"] + + ssl_certificate: + description: + - The name of the SSL certificate to use for SSL acceleration. + required: false + + ssl_algorithm: + description: + - Permitted encryption algorithms for SSL sessions according to encryption strength. + - choice | high | High encryption. Allow only AES and ChaCha. + - choice | medium | Medium encryption. Allow AES, ChaCha, 3DES, and RC4. + - choice | low | Low encryption. Allow AES, ChaCha, 3DES, RC4, and DES. + - choice | custom | Custom encryption. Use config ssl-cipher-suites to select the cipher suites that are allowed. + required: false + choices: ["high", "medium", "low", "custom"] + + srcintf_filter: + description: + - Interfaces to which the VIP applies. Separate the names with spaces. + required: false + + src_filter: + description: + - Source address filter. Each address must be either an IP/subnet (x.x.x.x/n) or a range (x.x.x.x-y.y.y.y). + - Separate addresses with spaces. + required: false + + service: + description: + - Service name. + required: false + + server_type: + description: + - Protocol to be load balanced by the virtual server (also called the server load balance virtual IP). + - choice | http | HTTP + - choice | https | HTTPS + - choice | ssl | SSL + - choice | tcp | TCP + - choice | udp | UDP + - choice | ip | IP + - choice | imaps | IMAPS + - choice | pop3s | POP3S + - choice | smtps | SMTPS + required: false + choices: ["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", "smtps"] + + protocol: + description: + - Protocol to use when forwarding packets. + - choice | tcp | TCP. + - choice | udp | UDP. + - choice | sctp | SCTP. + - choice | icmp | ICMP. + required: false + choices: ["tcp", "udp", "sctp", "icmp"] + + portmapping_type: + description: + - Port mapping type. + - choice | 1-to-1 | One to one. + - choice | m-to-n | Many to many. + required: false + choices: ["1-to-1", "m-to-n"] + + portforward: + description: + - Enable/disable port forwarding. + - choice | disable | Disable port forward. + - choice | enable | Enable port forward. + required: false + choices: ["disable", "enable"] + + persistence: + description: + - Configure how to make sure that clients connect to the same server every time they make a request that is part + - of the same session. + - choice | none | None. + - choice | http-cookie | HTTP cookie. + - choice | ssl-session-id | SSL session ID. + required: false + choices: ["none", "http-cookie", "ssl-session-id"] + + outlook_web_access: + description: + - Enable to add the Front-End-Https header for Microsoft Outlook Web Access. + - choice | disable | Disable Outlook Web Access support. + - choice | enable | Enable Outlook Web Access support. + required: false + choices: ["disable", "enable"] + + nat_source_vip: + description: + - Enable to prevent unintended servers from using a virtual IP. + - Disable to use the actual IP address of the server as the source address. + - choice | disable | Do not force to NAT as VIP. + - choice | enable | Force to NAT as VIP. + required: false + choices: ["disable", "enable"] + + name: + description: + - Virtual IP name. + required: false + + monitor: + description: + - Name of the health check monitor to use when polling to determine a virtual server's connectivity status. + required: false + + max_embryonic_connections: + description: + - Maximum number of incomplete connections. + required: false + + mappedport: + description: + - Port number range on the destination network to which the external port number range is mapped. + required: false + + mappedip: + description: + - IP address or address range on the destination network to which the external IP address is mapped. + required: false + + mapped_addr: + description: + - Mapped FQDN address name. + required: false + + ldb_method: + description: + - Method used to distribute sessions to real servers. + - choice | static | Distribute to server based on source IP. + - choice | round-robin | Distribute to server based round robin order. + - choice | weighted | Distribute to server based on weight. + - choice | least-session | Distribute to server with lowest session count. + - choice | least-rtt | Distribute to server with lowest Round-Trip-Time. + - choice | first-alive | Distribute to the first server that is alive. + - choice | http-host | Distribute to server based on host field in HTTP header. + required: false + choices: ["static", "round-robin", "weighted", "least-session", "least-rtt", "first-alive", "http-host"] + + https_cookie_secure: + description: + - Enable/disable verification that inserted HTTPS cookies are secure. + - choice | disable | Do not mark cookie as secure, allow sharing between an HTTP and HTTPS connection. + - choice | enable | Mark inserted cookie as secure, cookie can only be used for HTTPS a connection. + required: false + choices: ["disable", "enable"] + + http_multiplex: + description: + - Enable/disable HTTP multiplexing. + - choice | disable | Disable HTTP session multiplexing. + - choice | enable | Enable HTTP session multiplexing. + required: false + choices: ["disable", "enable"] + + http_ip_header_name: + description: + - For HTTP multiplexing, enter a custom HTTPS header name. The orig client IP address is added to this header. + - If empty, X-Forwarded-For is used. + required: false + + http_ip_header: + description: + - For HTTP multiplexing, enable to add the original client IP address in the XForwarded-For HTTP header. + - choice | disable | Disable adding HTTP header. + - choice | enable | Enable adding HTTP header. + required: false + choices: ["disable", "enable"] + + http_cookie_share: + description: + - Control sharing of cookies across virtual servers. same-ip means a cookie from one virtual server can be used + - by another. Disable stops cookie sharing. + - choice | disable | Only allow HTTP cookie to match this virtual server. + - choice | same-ip | Allow HTTP cookie to match any virtual server with same IP. + required: false + choices: ["disable", "same-ip"] + + http_cookie_path: + description: + - Limit HTTP cookie persistence to the specified path. + required: false + + http_cookie_generation: + description: + - Generation of HTTP cookie to be accepted. Changing invalidates all existing cookies. + required: false + + http_cookie_domain_from_host: + description: + - Enable/disable use of HTTP cookie domain from host field in HTTP. + - choice | disable | Disable use of HTTP cookie domain from host field in HTTP (use http-cooke-domain setting). + - choice | enable | Enable use of HTTP cookie domain from host field in HTTP. + required: false + choices: ["disable", "enable"] + + http_cookie_domain: + description: + - Domain that HTTP cookie persistence should apply to. + required: false + + http_cookie_age: + description: + - Time in minutes that client web browsers should keep a cookie. Default is 60 seconds. 0 = no time limit. + required: false + + gratuitous_arp_interval: + description: + - Enable to have the VIP send gratuitous ARPs. 0=disabled. Set from 5 up to 8640000 seconds to enable. + required: false + + extport: + description: + - Incoming port number range that you want to map to a port number range on the destination network. + required: false + + extip: + description: + - IP address or address range on the external interface that you want to map to an address or address range on t + - he destination network. + required: false + + extintf: + description: + - Interface connected to the source network that receives the packets that will be forwarded to the destination + - network. + required: false + + extaddr: + description: + - External FQDN address name. + required: false + + dns_mapping_ttl: + description: + - DNS mapping TTL (Set to zero to use TTL in DNS response, default = 0). + required: false + + comment: + description: + - Comment. + required: false + + color: + description: + - Color of icon on the GUI. + required: false + + arp_reply: + description: + - Enable to respond to ARP requests for this virtual IP address. Enabled by default. + - choice | disable | Disable ARP reply. + - choice | enable | Enable ARP reply. + required: false + choices: ["disable", "enable"] + + dynamic_mapping: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + dynamic_mapping_arp_reply: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_color: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_comment: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_dns_mapping_ttl: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_extaddr: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_extintf: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_extip: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_extport: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_gratuitous_arp_interval: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_http_cookie_age: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_http_cookie_domain: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_http_cookie_domain_from_host: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_http_cookie_generation: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_http_cookie_path: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_http_cookie_share: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | same-ip | + required: false + choices: ["disable", "same-ip"] + + dynamic_mapping_http_ip_header: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_http_ip_header_name: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_http_multiplex: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_https_cookie_secure: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ldb_method: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | static | + - choice | round-robin | + - choice | weighted | + - choice | least-session | + - choice | least-rtt | + - choice | first-alive | + - choice | http-host | + required: false + choices: ["static", "round-robin", "weighted", "least-session", "least-rtt", "first-alive", "http-host"] + + dynamic_mapping_mapped_addr: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_mappedip: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_mappedport: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_max_embryonic_connections: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_monitor: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_nat_source_vip: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_outlook_web_access: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_persistence: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | none | + - choice | http-cookie | + - choice | ssl-session-id | + required: false + choices: ["none", "http-cookie", "ssl-session-id"] + + dynamic_mapping_portforward: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_portmapping_type: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | 1-to-1 | + - choice | m-to-n | + required: false + choices: ["1-to-1", "m-to-n"] + + dynamic_mapping_protocol: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | tcp | + - choice | udp | + - choice | sctp | + - choice | icmp | + required: false + choices: ["tcp", "udp", "sctp", "icmp"] + + dynamic_mapping_server_type: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | http | + - choice | https | + - choice | ssl | + - choice | tcp | + - choice | udp | + - choice | ip | + - choice | imaps | + - choice | pop3s | + - choice | smtps | + required: false + choices: ["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", "smtps"] + + dynamic_mapping_service: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_src_filter: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_srcintf_filter: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_algorithm: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | high | + - choice | medium | + - choice | low | + - choice | custom | + required: false + choices: ["high", "medium", "low", "custom"] + + dynamic_mapping_ssl_certificate: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_client_fallback: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_client_renegotiation: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | deny | + - choice | allow | + - choice | secure | + required: false + choices: ["deny", "allow", "secure"] + + dynamic_mapping_ssl_client_session_state_max: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_client_session_state_timeout: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_client_session_state_type: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | time | + - choice | count | + - choice | both | + required: false + choices: ["disable", "time", "count", "both"] + + dynamic_mapping_ssl_dh_bits: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | 768 | + - choice | 1024 | + - choice | 1536 | + - choice | 2048 | + - choice | 3072 | + - choice | 4096 | + required: false + choices: ["768", "1024", "1536", "2048", "3072", "4096"] + + dynamic_mapping_ssl_hpkp: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + - choice | report-only | + required: false + choices: ["disable", "enable", "report-only"] + + dynamic_mapping_ssl_hpkp_age: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_hpkp_backup: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_hpkp_include_subdomains: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_hpkp_primary: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_hpkp_report_uri: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_hsts: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_hsts_age: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_hsts_include_subdomains: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_http_location_conversion: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_http_match_host: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_max_version: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | ssl-3.0 | + - choice | tls-1.0 | + - choice | tls-1.1 | + - choice | tls-1.2 | + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + dynamic_mapping_ssl_min_version: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | ssl-3.0 | + - choice | tls-1.0 | + - choice | tls-1.1 | + - choice | tls-1.2 | + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + dynamic_mapping_ssl_mode: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | half | + - choice | full | + required: false + choices: ["half", "full"] + + dynamic_mapping_ssl_pfs: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | require | + - choice | deny | + - choice | allow | + required: false + choices: ["require", "deny", "allow"] + + dynamic_mapping_ssl_send_empty_frags: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_ssl_server_algorithm: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | high | + - choice | low | + - choice | medium | + - choice | custom | + - choice | client | + required: false + choices: ["high", "low", "medium", "custom", "client"] + + dynamic_mapping_ssl_server_max_version: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | ssl-3.0 | + - choice | tls-1.0 | + - choice | tls-1.1 | + - choice | tls-1.2 | + - choice | client | + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"] + + dynamic_mapping_ssl_server_min_version: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | ssl-3.0 | + - choice | tls-1.0 | + - choice | tls-1.1 | + - choice | tls-1.2 | + - choice | client | + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"] + + dynamic_mapping_ssl_server_session_state_max: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_server_session_state_timeout: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_server_session_state_type: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | time | + - choice | count | + - choice | both | + required: false + choices: ["disable", "time", "count", "both"] + + dynamic_mapping_type: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | static-nat | + - choice | load-balance | + - choice | server-load-balance | + - choice | dns-translation | + - choice | fqdn | + required: false + choices: ["static-nat", "load-balance", "server-load-balance", "dns-translation", "fqdn"] + + dynamic_mapping_weblogic_server: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_websphere_server: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + required: false + choices: ["disable", "enable"] + + dynamic_mapping_realservers_client_ip: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_healthcheck: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | disable | + - choice | enable | + - choice | vip | + required: false + choices: ["disable", "enable", "vip"] + + dynamic_mapping_realservers_holddown_interval: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_http_host: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_ip: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_max_connections: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_monitor: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_port: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_seq: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_realservers_status: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | active | + - choice | standby | + - choice | disable | + required: false + choices: ["active", "standby", "disable"] + + dynamic_mapping_realservers_weight: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + required: false + + dynamic_mapping_ssl_cipher_suites_cipher: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - choice | TLS-RSA-WITH-RC4-128-MD5 | + - choice | TLS-RSA-WITH-RC4-128-SHA | + - choice | TLS-RSA-WITH-DES-CBC-SHA | + - choice | TLS-RSA-WITH-3DES-EDE-CBC-SHA | + - choice | TLS-RSA-WITH-AES-128-CBC-SHA | + - choice | TLS-RSA-WITH-AES-256-CBC-SHA | + - choice | TLS-RSA-WITH-AES-128-CBC-SHA256 | + - choice | TLS-RSA-WITH-AES-256-CBC-SHA256 | + - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA | + - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA | + - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 | + - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 | + - choice | TLS-RSA-WITH-SEED-CBC-SHA | + - choice | TLS-RSA-WITH-ARIA-128-CBC-SHA256 | + - choice | TLS-RSA-WITH-ARIA-256-CBC-SHA384 | + - choice | TLS-DHE-RSA-WITH-DES-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 | + - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 | + - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 | + - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 | + - choice | TLS-DHE-RSA-WITH-SEED-CBC-SHA | + - choice | TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256 | + - choice | TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384 | + - choice | TLS-ECDHE-RSA-WITH-RC4-128-SHA | + - choice | TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA | + - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA | + - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA | + - choice | TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | + - choice | TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256 | + - choice | TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | + - choice | TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 | + - choice | TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 | + - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA | + - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA | + - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA256 | + - choice | TLS-DHE-DSS-WITH-AES-128-GCM-SHA256 | + - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA256 | + - choice | TLS-DHE-DSS-WITH-AES-256-GCM-SHA384 | + - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 | + - choice | TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 | + - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 | + - choice | TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 | + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA | + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 | + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 | + - choice | TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 | + - choice | TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 | + - choice | TLS-RSA-WITH-AES-128-GCM-SHA256 | + - choice | TLS-RSA-WITH-AES-256-GCM-SHA384 | + - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA | + - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA | + - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256 | + - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256 | + - choice | TLS-DHE-DSS-WITH-SEED-CBC-SHA | + - choice | TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256 | + - choice | TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384 | + - choice | TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256 | + - choice | TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384 | + - choice | TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256 | + - choice | TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384 | + - choice | TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA | + - choice | TLS-DHE-DSS-WITH-DES-CBC-SHA | + required: false + choices: ["TLS-RSA-WITH-RC4-128-MD5", + "TLS-RSA-WITH-RC4-128-SHA", + "TLS-RSA-WITH-DES-CBC-SHA", + "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA", + "TLS-RSA-WITH-AES-256-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA256", + "TLS-RSA-WITH-AES-256-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-RSA-WITH-SEED-CBC-SHA", + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-RSA-WITH-DES-CBC-SHA", + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-SEED-CBC-SHA", + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "TLS-RSA-WITH-AES-128-GCM-SHA256", + "TLS-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-SEED-CBC-SHA", + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-DSS-WITH-DES-CBC-SHA"] + + dynamic_mapping_ssl_cipher_suites_versions: + description: + - Dynamic Mapping Version of Suffixed Option Name. Sub-Table. Same Descriptions as Parent. + - FLAG Based Options. Specify multiple in list form. + - flag | ssl-3.0 | + - flag | tls-1.0 | + - flag | tls-1.1 | + - flag | tls-1.2 | + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + realservers: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + realservers_client_ip: + description: + - Only clients in this IP range can connect to this real server. + required: false + + realservers_healthcheck: + description: + - Enable to check the responsiveness of the real server before forwarding traffic. + - choice | disable | Disable per server health check. + - choice | enable | Enable per server health check. + - choice | vip | Use health check defined in VIP. + required: false + choices: ["disable", "enable", "vip"] + + realservers_holddown_interval: + description: + - Time in seconds that the health check monitor monitors an unresponsive server that should be active. + required: false + + realservers_http_host: + description: + - HTTP server domain name in HTTP header. + required: false + + realservers_ip: + description: + - IP address of the real server. + required: false + + realservers_max_connections: + description: + - Max number of active connections that can be directed to the real server. When reached, sessions are sent to + - their real servers. + required: false + + realservers_monitor: + description: + - Name of the health check monitor to use when polling to determine a virtual server's connectivity status. + required: false + + realservers_port: + description: + - Port for communicating with the real server. Required if port forwarding is enabled. + required: false + + realservers_seq: + description: + - Real Server Sequence Number + required: false + + realservers_status: + description: + - Set the status of the real server to active so that it can accept traffic. + - Or on standby or disabled so no traffic is sent. + - choice | active | Server status active. + - choice | standby | Server status standby. + - choice | disable | Server status disable. + required: false + choices: ["active", "standby", "disable"] + + realservers_weight: + description: + - Weight of the real server. If weighted load balancing is enabled, the server with the highest weight gets more + - connections. + required: false + + ssl_cipher_suites: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ssl_cipher_suites_cipher: + description: + - Cipher suite name. + - choice | TLS-RSA-WITH-RC4-128-MD5 | Cipher suite TLS-RSA-WITH-RC4-128-MD5. + - choice | TLS-RSA-WITH-RC4-128-SHA | Cipher suite TLS-RSA-WITH-RC4-128-SHA. + - choice | TLS-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-RSA-WITH-DES-CBC-SHA. + - choice | TLS-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-RSA-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA. + - choice | TLS-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA. + - choice | TLS-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA256. + - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA. + - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA. + - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256. + - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256. + - choice | TLS-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-RSA-WITH-SEED-CBC-SHA. + - choice | TLS-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-RSA-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-DHE-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-DES-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-SEED-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-ECDHE-RSA-WITH-RC4-128-SHA | Cipher suite TLS-ECDHE-RSA-WITH-RC4-128-SHA. + - choice | TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA. + - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA. + - choice | TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256. + - choice | TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256. + - choice | TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-RSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-GCM-SHA256. + - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-DSS-WITH-AES-256-GCM-SHA384. + - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384. + - choice | TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA. + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384. + - choice | TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-RSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DSS-RSA-WITH-CAMELLIA-128-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-SEED-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC_SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC_SHA384. + - choice | TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-DES-CBC-SHA. + required: false + choices: ["TLS-RSA-WITH-RC4-128-MD5", + "TLS-RSA-WITH-RC4-128-SHA", + "TLS-RSA-WITH-DES-CBC-SHA", + "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA", + "TLS-RSA-WITH-AES-256-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA256", + "TLS-RSA-WITH-AES-256-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-RSA-WITH-SEED-CBC-SHA", + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-RSA-WITH-DES-CBC-SHA", + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-SEED-CBC-SHA", + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "TLS-RSA-WITH-AES-128-GCM-SHA256", + "TLS-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-SEED-CBC-SHA", + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-DSS-WITH-DES-CBC-SHA"] + + ssl_cipher_suites_versions: + description: + - SSL/TLS versions that the cipher suite can be used with. + - FLAG Based Options. Specify multiple in list form. + - flag | ssl-3.0 | SSL 3.0. + - flag | tls-1.0 | TLS 1.0. + - flag | tls-1.1 | TLS 1.1. + - flag | tls-1.2 | TLS 1.2. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + ssl_server_cipher_suites: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ssl_server_cipher_suites_cipher: + description: + - Cipher suite name. + - choice | TLS-RSA-WITH-RC4-128-MD5 | Cipher suite TLS-RSA-WITH-RC4-128-MD5. + - choice | TLS-RSA-WITH-RC4-128-SHA | Cipher suite TLS-RSA-WITH-RC4-128-SHA. + - choice | TLS-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-RSA-WITH-DES-CBC-SHA. + - choice | TLS-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-RSA-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA. + - choice | TLS-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA. + - choice | TLS-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-AES-256-CBC-SHA256. + - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA. + - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA. + - choice | TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256. + - choice | TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256. + - choice | TLS-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-RSA-WITH-SEED-CBC-SHA. + - choice | TLS-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-RSA-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-RSA-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-DHE-RSA-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-DES-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-256-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-RSA-WITH-SEED-CBC-SHA. + - choice | TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-ECDHE-RSA-WITH-RC4-128-SHA | Cipher suite TLS-ECDHE-RSA-WITH-RC4-128-SHA. + - choice | TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA. + - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA. + - choice | TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256 | Suite TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256. + - choice | TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256 | Cipher suite TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256. + - choice | TLS-DHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-RSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-DHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-RSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-128-GCM-SHA256. + - choice | TLS-DHE-DSS-WITH-AES-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-AES-256-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-DHE-DSS-WITH-AES-256-GCM-SHA384. + - choice | TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384. + - choice | TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA. + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384. + - choice | TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-RSA-WITH-AES-128-GCM-SHA256 | Cipher suite TLS-RSA-WITH-AES-128-GCM-SHA256. + - choice | TLS-RSA-WITH-AES-256-GCM-SHA384 | Cipher suite TLS-RSA-WITH-AES-256-GCM-SHA384. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA | Cipher suite TLS-DSS-RSA-WITH-CAMELLIA-128-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-SEED-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-SEED-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256. + - choice | TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384. + - choice | TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC_SHA256. + - choice | TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384 | Cipher suite TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC_SHA384. + - choice | TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA. + - choice | TLS-DHE-DSS-WITH-DES-CBC-SHA | Cipher suite TLS-DHE-DSS-WITH-DES-CBC-SHA. + required: false + choices: ["TLS-RSA-WITH-RC4-128-MD5", + "TLS-RSA-WITH-RC4-128-SHA", + "TLS-RSA-WITH-DES-CBC-SHA", + "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA", + "TLS-RSA-WITH-AES-256-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA256", + "TLS-RSA-WITH-AES-256-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-RSA-WITH-SEED-CBC-SHA", + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-RSA-WITH-DES-CBC-SHA", + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-SEED-CBC-SHA", + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "TLS-RSA-WITH-AES-128-GCM-SHA256", + "TLS-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-SEED-CBC-SHA", + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-DSS-WITH-DES-CBC-SHA"] + + ssl_server_cipher_suites_priority: + description: + - SSL/TLS cipher suites priority. + required: false + + ssl_server_cipher_suites_versions: + description: + - SSL/TLS versions that the cipher suite can be used with. + - FLAG Based Options. Specify multiple in list form. + - flag | ssl-3.0 | SSL 3.0. + - flag | tls-1.0 | TLS 1.0. + - flag | tls-1.1 | TLS 1.1. + - flag | tls-1.2 | TLS 1.2. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + +''' + +EXAMPLES = ''' +# BASIC FULL STATIC NAT MAPPING +- name: EDIT FMGR_FIREWALL_VIP SNAT + community.fortios.fmgr_fwobj_vip: + name: "Basic StaticNAT Map" + mode: "set" + adom: "ansible" + type: "static-nat" + extip: "82.72.192.185" + extintf: "any" + mappedip: "10.7.220.25" + comment: "Created by Ansible" + color: "17" + +# BASIC PORT PNAT MAPPING +- name: EDIT FMGR_FIREWALL_VIP PNAT + community.fortios.fmgr_fwobj_vip: + name: "Basic PNAT Map Port 10443" + mode: "set" + adom: "ansible" + type: "static-nat" + extip: "82.72.192.185" + extport: "10443" + extintf: "any" + portforward: "enable" + protocol: "tcp" + mappedip: "10.7.220.25" + mappedport: "443" + comment: "Created by Ansible" + color: "17" + +# BASIC DNS TRANSLATION NAT +- name: EDIT FMGR_FIREWALL_DNST + community.fortios.fmgr_fwobj_vip: + name: "Basic DNS Translation" + mode: "set" + adom: "ansible" + type: "dns-translation" + extip: "192.168.0.1-192.168.0.100" + extintf: "dmz" + mappedip: "3.3.3.0/24, 4.0.0.0/24" + comment: "Created by Ansible" + color: "12" + +# BASIC FQDN NAT +- name: EDIT FMGR_FIREWALL_FQDN + community.fortios.fmgr_fwobj_vip: + name: "Basic FQDN Translation" + mode: "set" + adom: "ansible" + type: "fqdn" + mapped_addr: "google-play" + comment: "Created by Ansible" + color: "5" + +# DELETE AN ENTRY +- name: DELETE FMGR_FIREWALL_VIP PNAT + community.fortios.fmgr_fwobj_vip: + name: "Basic PNAT Map Port 10443" + mode: "delete" + adom: "ansible" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +def fmgr_firewall_vip_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/firewall/vip'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/firewall/vip/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + websphere_server=dict(required=False, type="str", choices=["disable", "enable"]), + weblogic_server=dict(required=False, type="str", choices=["disable", "enable"]), + type=dict(required=False, type="str", + choices=["static-nat", "load-balance", "server-load-balance", "dns-translation", "fqdn"]), + ssl_server_session_state_type=dict(required=False, type="str", choices=["disable", "time", "count", "both"]), + ssl_server_session_state_timeout=dict(required=False, type="int"), + ssl_server_session_state_max=dict(required=False, type="int"), + ssl_server_min_version=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]), + ssl_server_max_version=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]), + ssl_server_algorithm=dict(required=False, type="str", choices=["high", "low", "medium", "custom", "client"]), + ssl_send_empty_frags=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_pfs=dict(required=False, type="str", choices=["require", "deny", "allow"]), + ssl_mode=dict(required=False, type="str", choices=["half", "full"]), + ssl_min_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + ssl_max_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + ssl_http_match_host=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_http_location_conversion=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_hsts_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_hsts_age=dict(required=False, type="int"), + ssl_hsts=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_hpkp_report_uri=dict(required=False, type="str"), + ssl_hpkp_primary=dict(required=False, type="str"), + ssl_hpkp_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_hpkp_backup=dict(required=False, type="str"), + ssl_hpkp_age=dict(required=False, type="int"), + ssl_hpkp=dict(required=False, type="str", choices=["disable", "enable", "report-only"]), + ssl_dh_bits=dict(required=False, type="str", choices=["768", "1024", "1536", "2048", "3072", "4096"]), + ssl_client_session_state_type=dict(required=False, type="str", choices=["disable", "time", "count", "both"]), + ssl_client_session_state_timeout=dict(required=False, type="int"), + ssl_client_session_state_max=dict(required=False, type="int"), + ssl_client_renegotiation=dict(required=False, type="str", choices=["deny", "allow", "secure"]), + ssl_client_fallback=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_certificate=dict(required=False, type="str"), + ssl_algorithm=dict(required=False, type="str", choices=["high", "medium", "low", "custom"]), + srcintf_filter=dict(required=False, type="str"), + src_filter=dict(required=False, type="str"), + service=dict(required=False, type="str"), + server_type=dict(required=False, type="str", + choices=["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", "smtps"]), + protocol=dict(required=False, type="str", choices=["tcp", "udp", "sctp", "icmp"]), + portmapping_type=dict(required=False, type="str", choices=["1-to-1", "m-to-n"]), + portforward=dict(required=False, type="str", choices=["disable", "enable"]), + persistence=dict(required=False, type="str", choices=["none", "http-cookie", "ssl-session-id"]), + outlook_web_access=dict(required=False, type="str", choices=["disable", "enable"]), + nat_source_vip=dict(required=False, type="str", choices=["disable", "enable"]), + name=dict(required=False, type="str"), + monitor=dict(required=False, type="str"), + max_embryonic_connections=dict(required=False, type="int"), + mappedport=dict(required=False, type="str"), + mappedip=dict(required=False, type="str"), + mapped_addr=dict(required=False, type="str"), + ldb_method=dict(required=False, type="str", + choices=["static", "round-robin", "weighted", "least-session", "least-rtt", "first-alive", + "http-host"]), + https_cookie_secure=dict(required=False, type="str", choices=["disable", "enable"]), + http_multiplex=dict(required=False, type="str", choices=["disable", "enable"]), + http_ip_header_name=dict(required=False, type="str"), + http_ip_header=dict(required=False, type="str", choices=["disable", "enable"]), + http_cookie_share=dict(required=False, type="str", choices=["disable", "same-ip"]), + http_cookie_path=dict(required=False, type="str"), + http_cookie_generation=dict(required=False, type="int"), + http_cookie_domain_from_host=dict(required=False, type="str", choices=["disable", "enable"]), + http_cookie_domain=dict(required=False, type="str"), + http_cookie_age=dict(required=False, type="int"), + gratuitous_arp_interval=dict(required=False, type="int"), + extport=dict(required=False, type="str"), + extip=dict(required=False, type="str"), + extintf=dict(required=False, type="str"), + extaddr=dict(required=False, type="str"), + dns_mapping_ttl=dict(required=False, type="int"), + comment=dict(required=False, type="str"), + color=dict(required=False, type="int"), + arp_reply=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping=dict(required=False, type="list"), + dynamic_mapping_arp_reply=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_color=dict(required=False, type="int"), + dynamic_mapping_comment=dict(required=False, type="str"), + dynamic_mapping_dns_mapping_ttl=dict(required=False, type="int"), + dynamic_mapping_extaddr=dict(required=False, type="str"), + dynamic_mapping_extintf=dict(required=False, type="str"), + dynamic_mapping_extip=dict(required=False, type="str"), + dynamic_mapping_extport=dict(required=False, type="str"), + dynamic_mapping_gratuitous_arp_interval=dict(required=False, type="int"), + dynamic_mapping_http_cookie_age=dict(required=False, type="int"), + dynamic_mapping_http_cookie_domain=dict(required=False, type="str"), + dynamic_mapping_http_cookie_domain_from_host=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_http_cookie_generation=dict(required=False, type="int"), + dynamic_mapping_http_cookie_path=dict(required=False, type="str"), + dynamic_mapping_http_cookie_share=dict(required=False, type="str", choices=["disable", "same-ip"]), + dynamic_mapping_http_ip_header=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_http_ip_header_name=dict(required=False, type="str"), + dynamic_mapping_http_multiplex=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_https_cookie_secure=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ldb_method=dict(required=False, type="str", choices=["static", + "round-robin", + "weighted", + "least-session", + "least-rtt", + "first-alive", + "http-host"]), + dynamic_mapping_mapped_addr=dict(required=False, type="str"), + dynamic_mapping_mappedip=dict(required=False, type="str"), + dynamic_mapping_mappedport=dict(required=False, type="str"), + dynamic_mapping_max_embryonic_connections=dict(required=False, type="int"), + dynamic_mapping_monitor=dict(required=False, type="str"), + dynamic_mapping_nat_source_vip=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_outlook_web_access=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_persistence=dict(required=False, type="str", choices=["none", "http-cookie", "ssl-session-id"]), + dynamic_mapping_portforward=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_portmapping_type=dict(required=False, type="str", choices=["1-to-1", "m-to-n"]), + dynamic_mapping_protocol=dict(required=False, type="str", choices=["tcp", "udp", "sctp", "icmp"]), + dynamic_mapping_server_type=dict(required=False, type="str", + choices=["http", "https", "ssl", "tcp", "udp", "ip", "imaps", "pop3s", + "smtps"]), + dynamic_mapping_service=dict(required=False, type="str"), + dynamic_mapping_src_filter=dict(required=False, type="str"), + dynamic_mapping_srcintf_filter=dict(required=False, type="str"), + dynamic_mapping_ssl_algorithm=dict(required=False, type="str", choices=["high", "medium", "low", "custom"]), + dynamic_mapping_ssl_certificate=dict(required=False, type="str"), + dynamic_mapping_ssl_client_fallback=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_client_renegotiation=dict(required=False, type="str", choices=["deny", "allow", "secure"]), + dynamic_mapping_ssl_client_session_state_max=dict(required=False, type="int"), + dynamic_mapping_ssl_client_session_state_timeout=dict(required=False, type="int"), + dynamic_mapping_ssl_client_session_state_type=dict(required=False, type="str", + choices=["disable", "time", "count", "both"]), + dynamic_mapping_ssl_dh_bits=dict(required=False, type="str", + choices=["768", "1024", "1536", "2048", "3072", "4096"]), + dynamic_mapping_ssl_hpkp=dict(required=False, type="str", choices=["disable", "enable", "report-only"]), + dynamic_mapping_ssl_hpkp_age=dict(required=False, type="int"), + dynamic_mapping_ssl_hpkp_backup=dict(required=False, type="str"), + dynamic_mapping_ssl_hpkp_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_hpkp_primary=dict(required=False, type="str"), + dynamic_mapping_ssl_hpkp_report_uri=dict(required=False, type="str"), + dynamic_mapping_ssl_hsts=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_hsts_age=dict(required=False, type="int"), + dynamic_mapping_ssl_hsts_include_subdomains=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_http_location_conversion=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_http_match_host=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_max_version=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + dynamic_mapping_ssl_min_version=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + dynamic_mapping_ssl_mode=dict(required=False, type="str", choices=["half", "full"]), + dynamic_mapping_ssl_pfs=dict(required=False, type="str", choices=["require", "deny", "allow"]), + dynamic_mapping_ssl_send_empty_frags=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_ssl_server_algorithm=dict(required=False, type="str", + choices=["high", "low", "medium", "custom", "client"]), + dynamic_mapping_ssl_server_max_version=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]), + dynamic_mapping_ssl_server_min_version=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2", "client"]), + dynamic_mapping_ssl_server_session_state_max=dict(required=False, type="int"), + dynamic_mapping_ssl_server_session_state_timeout=dict(required=False, type="int"), + dynamic_mapping_ssl_server_session_state_type=dict(required=False, type="str", + choices=["disable", "time", "count", "both"]), + dynamic_mapping_type=dict(required=False, type="str", + choices=["static-nat", "load-balance", "server-load-balance", "dns-translation", + "fqdn"]), + dynamic_mapping_weblogic_server=dict(required=False, type="str", choices=["disable", "enable"]), + dynamic_mapping_websphere_server=dict(required=False, type="str", choices=["disable", "enable"]), + + dynamic_mapping_realservers_client_ip=dict(required=False, type="str"), + dynamic_mapping_realservers_healthcheck=dict(required=False, type="str", choices=["disable", "enable", "vip"]), + dynamic_mapping_realservers_holddown_interval=dict(required=False, type="int"), + dynamic_mapping_realservers_http_host=dict(required=False, type="str"), + dynamic_mapping_realservers_ip=dict(required=False, type="str"), + dynamic_mapping_realservers_max_connections=dict(required=False, type="int"), + dynamic_mapping_realservers_monitor=dict(required=False, type="str"), + dynamic_mapping_realservers_port=dict(required=False, type="int"), + dynamic_mapping_realservers_seq=dict(required=False, type="str"), + dynamic_mapping_realservers_status=dict(required=False, type="str", choices=["active", "standby", "disable"]), + dynamic_mapping_realservers_weight=dict(required=False, type="int"), + + dynamic_mapping_ssl_cipher_suites_cipher=dict(required=False, + type="str", + choices=["TLS-RSA-WITH-RC4-128-MD5", + "TLS-RSA-WITH-RC4-128-SHA", + "TLS-RSA-WITH-DES-CBC-SHA", + "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA", + "TLS-RSA-WITH-AES-256-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA256", + "TLS-RSA-WITH-AES-256-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-RSA-WITH-SEED-CBC-SHA", + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-RSA-WITH-DES-CBC-SHA", + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-SEED-CBC-SHA", + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "TLS-RSA-WITH-AES-128-GCM-SHA256", + "TLS-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-SEED-CBC-SHA", + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-DSS-WITH-DES-CBC-SHA"]), + dynamic_mapping_ssl_cipher_suites_versions=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + realservers=dict(required=False, type="list"), + realservers_client_ip=dict(required=False, type="str"), + realservers_healthcheck=dict(required=False, type="str", choices=["disable", "enable", "vip"]), + realservers_holddown_interval=dict(required=False, type="int"), + realservers_http_host=dict(required=False, type="str"), + realservers_ip=dict(required=False, type="str"), + realservers_max_connections=dict(required=False, type="int"), + realservers_monitor=dict(required=False, type="str"), + realservers_port=dict(required=False, type="int"), + realservers_seq=dict(required=False, type="str"), + realservers_status=dict(required=False, type="str", choices=["active", "standby", "disable"]), + realservers_weight=dict(required=False, type="int"), + ssl_cipher_suites=dict(required=False, type="list"), + ssl_cipher_suites_cipher=dict(required=False, + type="str", + choices=["TLS-RSA-WITH-RC4-128-MD5", + "TLS-RSA-WITH-RC4-128-SHA", + "TLS-RSA-WITH-DES-CBC-SHA", + "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA", + "TLS-RSA-WITH-AES-256-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA256", + "TLS-RSA-WITH-AES-256-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-RSA-WITH-SEED-CBC-SHA", + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-RSA-WITH-DES-CBC-SHA", + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-SEED-CBC-SHA", + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "TLS-RSA-WITH-AES-128-GCM-SHA256", + "TLS-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-SEED-CBC-SHA", + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-DSS-WITH-DES-CBC-SHA"]), + ssl_cipher_suites_versions=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + ssl_server_cipher_suites=dict(required=False, type="list"), + ssl_server_cipher_suites_cipher=dict(required=False, + type="str", + choices=["TLS-RSA-WITH-RC4-128-MD5", + "TLS-RSA-WITH-RC4-128-SHA", + "TLS-RSA-WITH-DES-CBC-SHA", + "TLS-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA", + "TLS-RSA-WITH-AES-256-CBC-SHA", + "TLS-RSA-WITH-AES-128-CBC-SHA256", + "TLS-RSA-WITH-AES-256-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-RSA-WITH-SEED-CBC-SHA", + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-RSA-WITH-DES-CBC-SHA", + "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-RSA-WITH-SEED-CBC-SHA", + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-RC4-128-SHA", + "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA", + "TLS-DHE-DSS-WITH-AES-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-128-GCM-SHA256", + "TLS-DHE-DSS-WITH-AES-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + "TLS-RSA-WITH-AES-128-GCM-SHA256", + "TLS-RSA-WITH-AES-256-GCM-SHA384", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA", + "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256", + "TLS-DHE-DSS-WITH-SEED-CBC-SHA", + "TLS-DHE-DSS-WITH-ARIA-128-CBC-SHA256", + "TLS-DHE-DSS-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA", + "TLS-DHE-DSS-WITH-DES-CBC-SHA"]), + ssl_server_cipher_suites_priority=dict(required=False, type="str"), + ssl_server_cipher_suites_versions=dict(required=False, type="str", + choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "websphere-server": module.params["websphere_server"], + "weblogic-server": module.params["weblogic_server"], + "type": module.params["type"], + "ssl-server-session-state-type": module.params["ssl_server_session_state_type"], + "ssl-server-session-state-timeout": module.params["ssl_server_session_state_timeout"], + "ssl-server-session-state-max": module.params["ssl_server_session_state_max"], + "ssl-server-min-version": module.params["ssl_server_min_version"], + "ssl-server-max-version": module.params["ssl_server_max_version"], + "ssl-server-algorithm": module.params["ssl_server_algorithm"], + "ssl-send-empty-frags": module.params["ssl_send_empty_frags"], + "ssl-pfs": module.params["ssl_pfs"], + "ssl-mode": module.params["ssl_mode"], + "ssl-min-version": module.params["ssl_min_version"], + "ssl-max-version": module.params["ssl_max_version"], + "ssl-http-match-host": module.params["ssl_http_match_host"], + "ssl-http-location-conversion": module.params["ssl_http_location_conversion"], + "ssl-hsts-include-subdomains": module.params["ssl_hsts_include_subdomains"], + "ssl-hsts-age": module.params["ssl_hsts_age"], + "ssl-hsts": module.params["ssl_hsts"], + "ssl-hpkp-report-uri": module.params["ssl_hpkp_report_uri"], + "ssl-hpkp-primary": module.params["ssl_hpkp_primary"], + "ssl-hpkp-include-subdomains": module.params["ssl_hpkp_include_subdomains"], + "ssl-hpkp-backup": module.params["ssl_hpkp_backup"], + "ssl-hpkp-age": module.params["ssl_hpkp_age"], + "ssl-hpkp": module.params["ssl_hpkp"], + "ssl-dh-bits": module.params["ssl_dh_bits"], + "ssl-client-session-state-type": module.params["ssl_client_session_state_type"], + "ssl-client-session-state-timeout": module.params["ssl_client_session_state_timeout"], + "ssl-client-session-state-max": module.params["ssl_client_session_state_max"], + "ssl-client-renegotiation": module.params["ssl_client_renegotiation"], + "ssl-client-fallback": module.params["ssl_client_fallback"], + "ssl-certificate": module.params["ssl_certificate"], + "ssl-algorithm": module.params["ssl_algorithm"], + "srcintf-filter": module.params["srcintf_filter"], + "src-filter": module.params["src_filter"], + "service": module.params["service"], + "server-type": module.params["server_type"], + "protocol": module.params["protocol"], + "portmapping-type": module.params["portmapping_type"], + "portforward": module.params["portforward"], + "persistence": module.params["persistence"], + "outlook-web-access": module.params["outlook_web_access"], + "nat-source-vip": module.params["nat_source_vip"], + "name": module.params["name"], + "monitor": module.params["monitor"], + "max-embryonic-connections": module.params["max_embryonic_connections"], + "mappedport": module.params["mappedport"], + "mappedip": module.params["mappedip"], + "mapped-addr": module.params["mapped_addr"], + "ldb-method": module.params["ldb_method"], + "https-cookie-secure": module.params["https_cookie_secure"], + "http-multiplex": module.params["http_multiplex"], + "http-ip-header-name": module.params["http_ip_header_name"], + "http-ip-header": module.params["http_ip_header"], + "http-cookie-share": module.params["http_cookie_share"], + "http-cookie-path": module.params["http_cookie_path"], + "http-cookie-generation": module.params["http_cookie_generation"], + "http-cookie-domain-from-host": module.params["http_cookie_domain_from_host"], + "http-cookie-domain": module.params["http_cookie_domain"], + "http-cookie-age": module.params["http_cookie_age"], + "gratuitous-arp-interval": module.params["gratuitous_arp_interval"], + "extport": module.params["extport"], + "extip": module.params["extip"], + "extintf": module.params["extintf"], + "extaddr": module.params["extaddr"], + "dns-mapping-ttl": module.params["dns_mapping_ttl"], + "comment": module.params["comment"], + "color": module.params["color"], + "arp-reply": module.params["arp_reply"], + "dynamic_mapping": { + "arp-reply": module.params["dynamic_mapping_arp_reply"], + "color": module.params["dynamic_mapping_color"], + "comment": module.params["dynamic_mapping_comment"], + "dns-mapping-ttl": module.params["dynamic_mapping_dns_mapping_ttl"], + "extaddr": module.params["dynamic_mapping_extaddr"], + "extintf": module.params["dynamic_mapping_extintf"], + "extip": module.params["dynamic_mapping_extip"], + "extport": module.params["dynamic_mapping_extport"], + "gratuitous-arp-interval": module.params["dynamic_mapping_gratuitous_arp_interval"], + "http-cookie-age": module.params["dynamic_mapping_http_cookie_age"], + "http-cookie-domain": module.params["dynamic_mapping_http_cookie_domain"], + "http-cookie-domain-from-host": module.params["dynamic_mapping_http_cookie_domain_from_host"], + "http-cookie-generation": module.params["dynamic_mapping_http_cookie_generation"], + "http-cookie-path": module.params["dynamic_mapping_http_cookie_path"], + "http-cookie-share": module.params["dynamic_mapping_http_cookie_share"], + "http-ip-header": module.params["dynamic_mapping_http_ip_header"], + "http-ip-header-name": module.params["dynamic_mapping_http_ip_header_name"], + "http-multiplex": module.params["dynamic_mapping_http_multiplex"], + "https-cookie-secure": module.params["dynamic_mapping_https_cookie_secure"], + "ldb-method": module.params["dynamic_mapping_ldb_method"], + "mapped-addr": module.params["dynamic_mapping_mapped_addr"], + "mappedip": module.params["dynamic_mapping_mappedip"], + "mappedport": module.params["dynamic_mapping_mappedport"], + "max-embryonic-connections": module.params["dynamic_mapping_max_embryonic_connections"], + "monitor": module.params["dynamic_mapping_monitor"], + "nat-source-vip": module.params["dynamic_mapping_nat_source_vip"], + "outlook-web-access": module.params["dynamic_mapping_outlook_web_access"], + "persistence": module.params["dynamic_mapping_persistence"], + "portforward": module.params["dynamic_mapping_portforward"], + "portmapping-type": module.params["dynamic_mapping_portmapping_type"], + "protocol": module.params["dynamic_mapping_protocol"], + "server-type": module.params["dynamic_mapping_server_type"], + "service": module.params["dynamic_mapping_service"], + "src-filter": module.params["dynamic_mapping_src_filter"], + "srcintf-filter": module.params["dynamic_mapping_srcintf_filter"], + "ssl-algorithm": module.params["dynamic_mapping_ssl_algorithm"], + "ssl-certificate": module.params["dynamic_mapping_ssl_certificate"], + "ssl-client-fallback": module.params["dynamic_mapping_ssl_client_fallback"], + "ssl-client-renegotiation": module.params["dynamic_mapping_ssl_client_renegotiation"], + "ssl-client-session-state-max": module.params["dynamic_mapping_ssl_client_session_state_max"], + "ssl-client-session-state-timeout": module.params["dynamic_mapping_ssl_client_session_state_timeout"], + "ssl-client-session-state-type": module.params["dynamic_mapping_ssl_client_session_state_type"], + "ssl-dh-bits": module.params["dynamic_mapping_ssl_dh_bits"], + "ssl-hpkp": module.params["dynamic_mapping_ssl_hpkp"], + "ssl-hpkp-age": module.params["dynamic_mapping_ssl_hpkp_age"], + "ssl-hpkp-backup": module.params["dynamic_mapping_ssl_hpkp_backup"], + "ssl-hpkp-include-subdomains": module.params["dynamic_mapping_ssl_hpkp_include_subdomains"], + "ssl-hpkp-primary": module.params["dynamic_mapping_ssl_hpkp_primary"], + "ssl-hpkp-report-uri": module.params["dynamic_mapping_ssl_hpkp_report_uri"], + "ssl-hsts": module.params["dynamic_mapping_ssl_hsts"], + "ssl-hsts-age": module.params["dynamic_mapping_ssl_hsts_age"], + "ssl-hsts-include-subdomains": module.params["dynamic_mapping_ssl_hsts_include_subdomains"], + "ssl-http-location-conversion": module.params["dynamic_mapping_ssl_http_location_conversion"], + "ssl-http-match-host": module.params["dynamic_mapping_ssl_http_match_host"], + "ssl-max-version": module.params["dynamic_mapping_ssl_max_version"], + "ssl-min-version": module.params["dynamic_mapping_ssl_min_version"], + "ssl-mode": module.params["dynamic_mapping_ssl_mode"], + "ssl-pfs": module.params["dynamic_mapping_ssl_pfs"], + "ssl-send-empty-frags": module.params["dynamic_mapping_ssl_send_empty_frags"], + "ssl-server-algorithm": module.params["dynamic_mapping_ssl_server_algorithm"], + "ssl-server-max-version": module.params["dynamic_mapping_ssl_server_max_version"], + "ssl-server-min-version": module.params["dynamic_mapping_ssl_server_min_version"], + "ssl-server-session-state-max": module.params["dynamic_mapping_ssl_server_session_state_max"], + "ssl-server-session-state-timeout": module.params["dynamic_mapping_ssl_server_session_state_timeout"], + "ssl-server-session-state-type": module.params["dynamic_mapping_ssl_server_session_state_type"], + "type": module.params["dynamic_mapping_type"], + "weblogic-server": module.params["dynamic_mapping_weblogic_server"], + "websphere-server": module.params["dynamic_mapping_websphere_server"], + "realservers": { + "client-ip": module.params["dynamic_mapping_realservers_client_ip"], + "healthcheck": module.params["dynamic_mapping_realservers_healthcheck"], + "holddown-interval": module.params["dynamic_mapping_realservers_holddown_interval"], + "http-host": module.params["dynamic_mapping_realservers_http_host"], + "ip": module.params["dynamic_mapping_realservers_ip"], + "max-connections": module.params["dynamic_mapping_realservers_max_connections"], + "monitor": module.params["dynamic_mapping_realservers_monitor"], + "port": module.params["dynamic_mapping_realservers_port"], + "seq": module.params["dynamic_mapping_realservers_seq"], + "status": module.params["dynamic_mapping_realservers_status"], + "weight": module.params["dynamic_mapping_realservers_weight"], + }, + "ssl-cipher-suites": { + "cipher": module.params["dynamic_mapping_ssl_cipher_suites_cipher"], + "versions": module.params["dynamic_mapping_ssl_cipher_suites_versions"], + }, + }, + "realservers": { + "client-ip": module.params["realservers_client_ip"], + "healthcheck": module.params["realservers_healthcheck"], + "holddown-interval": module.params["realservers_holddown_interval"], + "http-host": module.params["realservers_http_host"], + "ip": module.params["realservers_ip"], + "max-connections": module.params["realservers_max_connections"], + "monitor": module.params["realservers_monitor"], + "port": module.params["realservers_port"], + "seq": module.params["realservers_seq"], + "status": module.params["realservers_status"], + "weight": module.params["realservers_weight"], + }, + "ssl-cipher-suites": { + "cipher": module.params["ssl_cipher_suites_cipher"], + "versions": module.params["ssl_cipher_suites_versions"], + }, + "ssl-server-cipher-suites": { + "cipher": module.params["ssl_server_cipher_suites_cipher"], + "priority": module.params["ssl_server_cipher_suites_priority"], + "versions": module.params["ssl_server_cipher_suites_versions"], + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['dynamic_mapping', 'realservers', 'ssl-cipher-suites', 'ssl-server-cipher-suites'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + try: + results = fmgr_firewall_vip_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwpol_ipv4.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwpol_ipv4.py new file mode 100644 index 00000000..f0b0fd9c --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwpol_ipv4.py @@ -0,0 +1,1355 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwpol_ipv4 +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Allows the add/delete of Firewall Policies on Packages in FortiManager. +description: + - Allows the add/delete of Firewall Policies on Packages in FortiManager. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + package_name: + description: + - The policy package you want to modify + required: false + default: "default" + + fail_on_missing_dependency: + description: + - Normal behavior is to "skip" tasks that fail dependency checks, so other tasks can run. + - If set to "enabled" if a failed dependency check happeens, Ansible will exit as with failure instead of skip. + required: false + default: "disable" + choices: ["enable", "disable"] + + wsso: + description: + - Enable/disable WiFi Single Sign On (WSSO). + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + webfilter_profile: + description: + - Name of an existing Web filter profile. + required: false + + webcache_https: + description: + - Enable/disable web cache for HTTPS. + - choice | disable | Disable web cache for HTTPS. + - choice | enable | Enable web cache for HTTPS. + required: false + choices: ["disable", "enable"] + + webcache: + description: + - Enable/disable web cache. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + wccp: + description: + - Enable/disable forwarding traffic matching this policy to a configured WCCP server. + - choice | disable | Disable WCCP setting. + - choice | enable | Enable WCCP setting. + required: false + choices: ["disable", "enable"] + + wanopt_profile: + description: + - WAN optimization profile. + required: false + + wanopt_peer: + description: + - WAN optimization peer. + required: false + + wanopt_passive_opt: + description: + - WAN optimization passive mode options. This option decides what IP address will be used to connect server. + - choice | default | Allow client side WAN opt peer to decide. + - choice | transparent | Use address of client to connect to server. + - choice | non-transparent | Use local FortiGate address to connect to server. + required: false + choices: ["default", "transparent", "non-transparent"] + + wanopt_detection: + description: + - WAN optimization auto-detection mode. + - choice | active | Active WAN optimization peer auto-detection. + - choice | passive | Passive WAN optimization peer auto-detection. + - choice | off | Turn off WAN optimization peer auto-detection. + required: false + choices: ["active", "passive", "off"] + + wanopt: + description: + - Enable/disable WAN optimization. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + waf_profile: + description: + - Name of an existing Web application firewall profile. + required: false + + vpntunnel: + description: + - Policy-based IPsec VPN | name of the IPsec VPN Phase 1. + required: false + + voip_profile: + description: + - Name of an existing VoIP profile. + required: false + + vlan_filter: + description: + - Set VLAN filters. + required: false + + vlan_cos_rev: + description: + - VLAN reverse direction user priority | 255 passthrough, 0 lowest, 7 highest.. + required: false + + vlan_cos_fwd: + description: + - VLAN forward direction user priority | 255 passthrough, 0 lowest, 7 highest. + required: false + + utm_status: + description: + - Enable to add one or more security profiles (AV, IPS, etc.) to the firewall policy. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + users: + description: + - Names of individual users that can authenticate with this policy. + required: false + + url_category: + description: + - URL category ID list. + required: false + + traffic_shaper_reverse: + description: + - Reverse traffic shaper. + required: false + + traffic_shaper: + description: + - Traffic shaper. + required: false + + timeout_send_rst: + description: + - Enable/disable sending RST packets when TCP sessions expire. + - choice | disable | Disable sending of RST packet upon TCP session expiration. + - choice | enable | Enable sending of RST packet upon TCP session expiration. + required: false + choices: ["disable", "enable"] + + tcp_session_without_syn: + description: + - Enable/disable creation of TCP session without SYN flag. + - choice | all | Enable TCP session without SYN. + - choice | data-only | Enable TCP session data only. + - choice | disable | Disable TCP session without SYN. + required: false + choices: ["all", "data-only", "disable"] + + tcp_mss_sender: + description: + - Sender TCP maximum segment size (MSS). + required: false + + tcp_mss_receiver: + description: + - Receiver TCP maximum segment size (MSS). + required: false + + status: + description: + - Enable or disable this policy. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ssl_ssh_profile: + description: + - Name of an existing SSL SSH profile. + required: false + + ssl_mirror_intf: + description: + - SSL mirror interface name. + required: false + + ssl_mirror: + description: + - Enable to copy decrypted SSL traffic to a FortiGate interface (called SSL mirroring). + - choice | disable | Disable SSL mirror. + - choice | enable | Enable SSL mirror. + required: false + choices: ["disable", "enable"] + + ssh_filter_profile: + description: + - Name of an existing SSH filter profile. + required: false + + srcintf: + description: + - Incoming (ingress) interface. + required: false + + srcaddr_negate: + description: + - When enabled srcaddr specifies what the source address must NOT be. + - choice | disable | Disable source address negate. + - choice | enable | Enable source address negate. + required: false + choices: ["disable", "enable"] + + srcaddr: + description: + - Source address and address group names. + required: false + + spamfilter_profile: + description: + - Name of an existing Spam filter profile. + required: false + + session_ttl: + description: + - TTL in seconds for sessions accepted by this policy (0 means use the system default session TTL). + required: false + + service_negate: + description: + - When enabled service specifies what the service must NOT be. + - choice | disable | Disable negated service match. + - choice | enable | Enable negated service match. + required: false + choices: ["disable", "enable"] + + service: + description: + - Service and service group names. + required: false + + send_deny_packet: + description: + - Enable to send a reply when a session is denied or blocked by a firewall policy. + - choice | disable | Disable deny-packet sending. + - choice | enable | Enable deny-packet sending. + required: false + choices: ["disable", "enable"] + + schedule_timeout: + description: + - Enable to force current sessions to end when the schedule object times out. + - choice | disable | Disable schedule timeout. + - choice | enable | Enable schedule timeout. + required: false + choices: ["disable", "enable"] + + schedule: + description: + - Schedule name. + required: false + + scan_botnet_connections: + description: + - Block or monitor connections to Botnet servers or disable Botnet scanning. + - choice | disable | Do not scan connections to botnet servers. + - choice | block | Block connections to botnet servers. + - choice | monitor | Log connections to botnet servers. + required: false + choices: ["disable", "block", "monitor"] + + rtp_nat: + description: + - Enable Real Time Protocol (RTP) NAT. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + rtp_addr: + description: + - Address names if this is an RTP NAT policy. + required: false + + rsso: + description: + - Enable/disable RADIUS single sign-on (RSSO). + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + replacemsg_override_group: + description: + - Override the default replacement message group for this policy. + required: false + + redirect_url: + description: + - URL users are directed to after seeing and accepting the disclaimer or authenticating. + required: false + + radius_mac_auth_bypass: + description: + - Enable MAC authentication bypass. The bypassed MAC address must be received from RADIUS server. + - choice | disable | Disable MAC authentication bypass. + - choice | enable | Enable MAC authentication bypass. + required: false + choices: ["disable", "enable"] + + profile_type: + description: + - Determine whether the firewall policy allows security profile groups or single profiles only. + - choice | single | Do not allow security profile groups. + - choice | group | Allow security profile groups. + required: false + choices: ["single", "group"] + + profile_protocol_options: + description: + - Name of an existing Protocol options profile. + required: false + + profile_group: + description: + - Name of profile group. + required: false + + poolname: + description: + - IP Pool names. + required: false + + policyid: + description: + - Policy ID. + required: false + + permit_stun_host: + description: + - Accept UDP packets from any Session Traversal Utilities for NAT (STUN) host. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + permit_any_host: + description: + - Accept UDP packets from any host. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + per_ip_shaper: + description: + - Per-IP traffic shaper. + required: false + + outbound: + description: + - Policy-based IPsec VPN | only traffic from the internal network can initiate a VPN. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ntlm_guest: + description: + - Enable/disable NTLM guest user access. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ntlm_enabled_browsers: + description: + - HTTP-User-Agent value of supported browsers. + required: false + + ntlm: + description: + - Enable/disable NTLM authentication. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + np_acceleration: + description: + - Enable/disable UTM Network Processor acceleration. + - choice | disable | Disable UTM Network Processor acceleration. + - choice | enable | Enable UTM Network Processor acceleration. + required: false + choices: ["disable", "enable"] + + natoutbound: + description: + - Policy-based IPsec VPN | apply source NAT to outbound traffic. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + natip: + description: + - Policy-based IPsec VPN | source NAT IP address for outgoing traffic. + required: false + + natinbound: + description: + - Policy-based IPsec VPN | apply destination NAT to inbound traffic. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + nat: + description: + - Enable/disable source NAT. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + name: + description: + - Policy name. + required: false + + mms_profile: + description: + - Name of an existing MMS profile. + required: false + + match_vip: + description: + - Enable to match packets that have had their destination addresses changed by a VIP. + - choice | disable | Do not match DNATed packet. + - choice | enable | Match DNATed packet. + required: false + choices: ["disable", "enable"] + + logtraffic_start: + description: + - Record logs when a session starts and ends. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + logtraffic: + description: + - Enable or disable logging. Log all sessions or security profile sessions. + - choice | disable | Disable all logging for this policy. + - choice | all | Log all sessions accepted or denied by this policy. + - choice | utm | Log traffic that has a security profile applied to it. + required: false + choices: ["disable", "all", "utm"] + + learning_mode: + description: + - Enable to allow everything, but log all of the meaningful data for security information gathering. + - choice | disable | Disable learning mode in firewall policy. + - choice | enable | Enable learning mode in firewall policy. + required: false + choices: ["disable", "enable"] + + label: + description: + - Label for the policy that appears when the GUI is in Section View mode. + required: false + + ips_sensor: + description: + - Name of an existing IPS sensor. + required: false + + ippool: + description: + - Enable to use IP Pools for source NAT. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + internet_service_src_negate: + description: + - When enabled internet-service-src specifies what the service must NOT be. + - choice | disable | Disable negated Internet Service source match. + - choice | enable | Enable negated Internet Service source match. + required: false + choices: ["disable", "enable"] + + internet_service_src_id: + description: + - Internet Service source ID. + required: false + + internet_service_src_custom: + description: + - Custom Internet Service source name. + required: false + + internet_service_src: + description: + - Enable/disable use of Internet Services in source for this policy. If enabled, source address is not used. + - choice | disable | Disable use of Internet Services source in policy. + - choice | enable | Enable use of Internet Services source in policy. + required: false + choices: ["disable", "enable"] + + internet_service_negate: + description: + - When enabled internet-service specifies what the service must NOT be. + - choice | disable | Disable negated Internet Service match. + - choice | enable | Enable negated Internet Service match. + required: false + choices: ["disable", "enable"] + + internet_service_id: + description: + - Internet Service ID. + required: false + + internet_service_custom: + description: + - Custom Internet Service name. + required: false + + internet_service: + description: + - Enable/disable use of Internet Services for this policy. If enabled, dstaddr and service are not used. + - choice | disable | Disable use of Internet Services in policy. + - choice | enable | Enable use of Internet Services in policy. + required: false + choices: ["disable", "enable"] + + inbound: + description: + - Policy-based IPsec VPN | only traffic from the remote network can initiate a VPN. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + identity_based_route: + description: + - Name of identity-based routing rule. + required: false + + icap_profile: + description: + - Name of an existing ICAP profile. + required: false + + gtp_profile: + description: + - GTP profile. + required: false + + groups: + description: + - Names of user groups that can authenticate with this policy. + required: false + + global_label: + description: + - Label for the policy that appears when the GUI is in Global View mode. + required: false + + fsso_agent_for_ntlm: + description: + - FSSO agent to use for NTLM authentication. + required: false + + fsso: + description: + - Enable/disable Fortinet Single Sign-On. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + fixedport: + description: + - Enable to prevent source NAT from changing a session's source port. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + firewall_session_dirty: + description: + - How to handle sessions if the configuration of this firewall policy changes. + - choice | check-all | Flush all current sessions accepted by this policy. + - choice | check-new | Continue to allow sessions already accepted by this policy. + required: false + choices: ["check-all", "check-new"] + + dstintf: + description: + - Outgoing (egress) interface. + required: false + + dstaddr_negate: + description: + - When enabled dstaddr specifies what the destination address must NOT be. + - choice | disable | Disable destination address negate. + - choice | enable | Enable destination address negate. + required: false + choices: ["disable", "enable"] + + dstaddr: + description: + - Destination address and address group names. + required: false + + dsri: + description: + - Enable DSRI to ignore HTTP server responses. + - choice | disable | Disable DSRI. + - choice | enable | Enable DSRI. + required: false + choices: ["disable", "enable"] + + dscp_value: + description: + - DSCP value. + required: false + + dscp_negate: + description: + - Enable negated DSCP match. + - choice | disable | Disable DSCP negate. + - choice | enable | Enable DSCP negate. + required: false + choices: ["disable", "enable"] + + dscp_match: + description: + - Enable DSCP check. + - choice | disable | Disable DSCP check. + - choice | enable | Enable DSCP check. + required: false + choices: ["disable", "enable"] + + dnsfilter_profile: + description: + - Name of an existing DNS filter profile. + required: false + + dlp_sensor: + description: + - Name of an existing DLP sensor. + required: false + + disclaimer: + description: + - Enable/disable user authentication disclaimer. + - choice | disable | Disable user authentication disclaimer. + - choice | enable | Enable user authentication disclaimer. + required: false + choices: ["disable", "enable"] + + diffservcode_rev: + description: + - Change packet's reverse (reply) DiffServ to this value. + required: false + + diffservcode_forward: + description: + - Change packet's DiffServ to this value. + required: false + + diffserv_reverse: + description: + - Enable to change packet's reverse (reply) DiffServ values to the specified diffservcode-rev value. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + diffserv_forward: + description: + - Enable to change packet's DiffServ values to the specified diffservcode-forward value. + - choice | disable | Disable WAN optimization. + - choice | enable | Enable WAN optimization. + required: false + choices: ["disable", "enable"] + + devices: + description: + - Names of devices or device groups that can be matched by the policy. + required: false + + delay_tcp_npu_session: + description: + - Enable TCP NPU session delay to guarantee packet order of 3-way handshake. + - choice | disable | Disable TCP NPU session delay in order to guarantee packet order of 3-way handshake. + - choice | enable | Enable TCP NPU session delay in order to guarantee packet order of 3-way handshake. + required: false + choices: ["disable", "enable"] + + custom_log_fields: + description: + - Custom fields to append to log messages for this policy. + required: false + + comments: + description: + - Comment. + required: false + + capture_packet: + description: + - Enable/disable capture packets. + - choice | disable | Disable capture packets. + - choice | enable | Enable capture packets. + required: false + choices: ["disable", "enable"] + + captive_portal_exempt: + description: + - Enable to exempt some users from the captive portal. + - choice | disable | Disable exemption of captive portal. + - choice | enable | Enable exemption of captive portal. + required: false + choices: ["disable", "enable"] + + block_notification: + description: + - Enable/disable block notification. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + av_profile: + description: + - Name of an existing Antivirus profile. + required: false + + auto_asic_offload: + description: + - Enable/disable offloading security profile processing to CP processors. + - choice | disable | Disable ASIC offloading. + - choice | enable | Enable auto ASIC offloading. + required: false + choices: ["disable", "enable"] + + auth_redirect_addr: + description: + - HTTP-to-HTTPS redirect address for firewall authentication. + required: false + + auth_path: + description: + - Enable/disable authentication-based routing. + - choice | disable | Disable authentication-based routing. + - choice | enable | Enable authentication-based routing. + required: false + choices: ["disable", "enable"] + + auth_cert: + description: + - HTTPS server certificate for policy authentication. + required: false + + application_list: + description: + - Name of an existing Application list. + required: false + + application: + description: + - Application ID list. + required: false + + app_group: + description: + - Application group names. + required: false + + app_category: + description: + - Application category ID list. + required: false + + action: + description: + - Policy action (allow/deny/ipsec). + - choice | deny | Blocks sessions that match the firewall policy. + - choice | accept | Allows session that match the firewall policy. + - choice | ipsec | Firewall policy becomes a policy-based IPsec VPN policy. + required: false + choices: ["deny", "accept", "ipsec"] + + vpn_dst_node: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + required: false + + vpn_dst_node_host: + description: + - VPN Destination Node Host. + required: false + + vpn_dst_node_seq: + description: + - VPN Destination Node Seq. + required: false + + vpn_dst_node_subnet: + description: + - VPN Destination Node Seq. + required: false + + vpn_src_node: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + required: false + + vpn_src_node_host: + description: + - VPN Source Node Host. + required: false + + vpn_src_node_seq: + description: + - VPN Source Node Seq. + required: false + + vpn_src_node_subnet: + description: + - VPN Source Node. + required: false + + +''' + +EXAMPLES = ''' +- name: ADD VERY BASIC IPV4 POLICY WITH NO NAT (WIDE OPEN) + community.fortios.fmgr_fwpol_ipv4: + mode: "set" + adom: "ansible" + package_name: "default" + name: "Basic_IPv4_Policy" + comments: "Created by Ansible" + action: "accept" + dstaddr: "all" + srcaddr: "all" + dstintf: "any" + srcintf: "any" + logtraffic: "utm" + service: "ALL" + schedule: "always" + +- name: ADD VERY BASIC IPV4 POLICY WITH NAT AND MULTIPLE ENTRIES + community.fortios.fmgr_fwpol_ipv4: + mode: "set" + adom: "ansible" + package_name: "default" + name: "Basic_IPv4_Policy_2" + comments: "Created by Ansible" + action: "accept" + dstaddr: "google-play" + srcaddr: "all" + dstintf: "any" + srcintf: "any" + logtraffic: "utm" + service: "HTTP, HTTPS" + schedule: "always" + nat: "enable" + users: "karen, kevin" + +- name: ADD VERY BASIC IPV4 POLICY WITH NAT AND MULTIPLE ENTRIES AND SEC PROFILES + community.fortios.fmgr_fwpol_ipv4: + mode: "set" + adom: "ansible" + package_name: "default" + name: "Basic_IPv4_Policy_3" + comments: "Created by Ansible" + action: "accept" + dstaddr: "google-play, autoupdate.opera.com" + srcaddr: "corp_internal" + dstintf: "zone_wan1, zone_wan2" + srcintf: "zone_int1" + logtraffic: "utm" + service: "HTTP, HTTPS" + schedule: "always" + nat: "enable" + users: "karen, kevin" + av_profile: "sniffer-profile" + ips_sensor: "default" + +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +def fmgr_firewall_policy_modify(fmgr, paramgram): + """ + fmgr_firewall_policy -- Add/Set/Deletes Firewall Policy Objects defined in the "paramgram" + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/pkg/{pkg}/firewall/policy'.format(adom=adom, pkg=paramgram["package_name"]) + datagram = scrub_dict((prepare_dict(paramgram))) + del datagram["package_name"] + datagram = fmgr._tools.split_comma_strings_into_lists(datagram) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + url = '/pm/config/adom/{adom}/pkg/{pkg}/firewall' \ + '/policy/{policyid}'.format(adom=paramgram["adom"], + pkg=paramgram["package_name"], + policyid=paramgram["policyid"]) + datagram = { + "policyid": paramgram["policyid"] + } + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + package_name=dict(type="str", required=False, default="default"), + fail_on_missing_dependency=dict(type="str", required=False, default="disable", choices=["enable", + "disable"]), + wsso=dict(required=False, type="str", choices=["disable", "enable"]), + webfilter_profile=dict(required=False, type="str"), + webcache_https=dict(required=False, type="str", choices=["disable", "enable"]), + webcache=dict(required=False, type="str", choices=["disable", "enable"]), + wccp=dict(required=False, type="str", choices=["disable", "enable"]), + wanopt_profile=dict(required=False, type="str"), + wanopt_peer=dict(required=False, type="str"), + wanopt_passive_opt=dict(required=False, type="str", choices=["default", "transparent", "non-transparent"]), + wanopt_detection=dict(required=False, type="str", choices=["active", "passive", "off"]), + wanopt=dict(required=False, type="str", choices=["disable", "enable"]), + waf_profile=dict(required=False, type="str"), + vpntunnel=dict(required=False, type="str"), + voip_profile=dict(required=False, type="str"), + vlan_filter=dict(required=False, type="str"), + vlan_cos_rev=dict(required=False, type="int"), + vlan_cos_fwd=dict(required=False, type="int"), + utm_status=dict(required=False, type="str", choices=["disable", "enable"]), + users=dict(required=False, type="str"), + url_category=dict(required=False, type="str"), + traffic_shaper_reverse=dict(required=False, type="str"), + traffic_shaper=dict(required=False, type="str"), + timeout_send_rst=dict(required=False, type="str", choices=["disable", "enable"]), + tcp_session_without_syn=dict(required=False, type="str", choices=["all", "data-only", "disable"]), + tcp_mss_sender=dict(required=False, type="int"), + tcp_mss_receiver=dict(required=False, type="int"), + status=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_ssh_profile=dict(required=False, type="str"), + ssl_mirror_intf=dict(required=False, type="str"), + ssl_mirror=dict(required=False, type="str", choices=["disable", "enable"]), + ssh_filter_profile=dict(required=False, type="str"), + srcintf=dict(required=False, type="str"), + srcaddr_negate=dict(required=False, type="str", choices=["disable", "enable"]), + srcaddr=dict(required=False, type="str"), + spamfilter_profile=dict(required=False, type="str"), + session_ttl=dict(required=False, type="int"), + service_negate=dict(required=False, type="str", choices=["disable", "enable"]), + service=dict(required=False, type="str"), + send_deny_packet=dict(required=False, type="str", choices=["disable", "enable"]), + schedule_timeout=dict(required=False, type="str", choices=["disable", "enable"]), + schedule=dict(required=False, type="str"), + scan_botnet_connections=dict(required=False, type="str", choices=["disable", "block", "monitor"]), + rtp_nat=dict(required=False, type="str", choices=["disable", "enable"]), + rtp_addr=dict(required=False, type="str"), + rsso=dict(required=False, type="str", choices=["disable", "enable"]), + replacemsg_override_group=dict(required=False, type="str"), + redirect_url=dict(required=False, type="str"), + radius_mac_auth_bypass=dict(required=False, type="str", choices=["disable", "enable"]), + profile_type=dict(required=False, type="str", choices=["single", "group"]), + profile_protocol_options=dict(required=False, type="str"), + profile_group=dict(required=False, type="str"), + poolname=dict(required=False, type="str"), + policyid=dict(required=False, type="str"), + permit_stun_host=dict(required=False, type="str", choices=["disable", "enable"]), + permit_any_host=dict(required=False, type="str", choices=["disable", "enable"]), + per_ip_shaper=dict(required=False, type="str"), + outbound=dict(required=False, type="str", choices=["disable", "enable"]), + ntlm_guest=dict(required=False, type="str", choices=["disable", "enable"]), + ntlm_enabled_browsers=dict(required=False, type="str"), + ntlm=dict(required=False, type="str", choices=["disable", "enable"]), + np_acceleration=dict(required=False, type="str", choices=["disable", "enable"]), + natoutbound=dict(required=False, type="str", choices=["disable", "enable"]), + natip=dict(required=False, type="str"), + natinbound=dict(required=False, type="str", choices=["disable", "enable"]), + nat=dict(required=False, type="str", choices=["disable", "enable"]), + name=dict(required=False, type="str"), + mms_profile=dict(required=False, type="str"), + match_vip=dict(required=False, type="str", choices=["disable", "enable"]), + logtraffic_start=dict(required=False, type="str", choices=["disable", "enable"]), + logtraffic=dict(required=False, type="str", choices=["disable", "all", "utm"]), + learning_mode=dict(required=False, type="str", choices=["disable", "enable"]), + label=dict(required=False, type="str"), + ips_sensor=dict(required=False, type="str"), + ippool=dict(required=False, type="str", choices=["disable", "enable"]), + internet_service_src_negate=dict(required=False, type="str", choices=["disable", "enable"]), + internet_service_src_id=dict(required=False, type="str"), + internet_service_src_custom=dict(required=False, type="str"), + internet_service_src=dict(required=False, type="str", choices=["disable", "enable"]), + internet_service_negate=dict(required=False, type="str", choices=["disable", "enable"]), + internet_service_id=dict(required=False, type="str"), + internet_service_custom=dict(required=False, type="str"), + internet_service=dict(required=False, type="str", choices=["disable", "enable"]), + inbound=dict(required=False, type="str", choices=["disable", "enable"]), + identity_based_route=dict(required=False, type="str"), + icap_profile=dict(required=False, type="str"), + gtp_profile=dict(required=False, type="str"), + groups=dict(required=False, type="str"), + global_label=dict(required=False, type="str"), + fsso_agent_for_ntlm=dict(required=False, type="str"), + fsso=dict(required=False, type="str", choices=["disable", "enable"]), + fixedport=dict(required=False, type="str", choices=["disable", "enable"]), + firewall_session_dirty=dict(required=False, type="str", choices=["check-all", "check-new"]), + dstintf=dict(required=False, type="str"), + dstaddr_negate=dict(required=False, type="str", choices=["disable", "enable"]), + dstaddr=dict(required=False, type="str"), + dsri=dict(required=False, type="str", choices=["disable", "enable"]), + dscp_value=dict(required=False, type="str"), + dscp_negate=dict(required=False, type="str", choices=["disable", "enable"]), + dscp_match=dict(required=False, type="str", choices=["disable", "enable"]), + dnsfilter_profile=dict(required=False, type="str"), + dlp_sensor=dict(required=False, type="str"), + disclaimer=dict(required=False, type="str", choices=["disable", "enable"]), + diffservcode_rev=dict(required=False, type="str"), + diffservcode_forward=dict(required=False, type="str"), + diffserv_reverse=dict(required=False, type="str", choices=["disable", "enable"]), + diffserv_forward=dict(required=False, type="str", choices=["disable", "enable"]), + devices=dict(required=False, type="str"), + delay_tcp_npu_session=dict(required=False, type="str", choices=["disable", "enable"]), + custom_log_fields=dict(required=False, type="str"), + comments=dict(required=False, type="str"), + capture_packet=dict(required=False, type="str", choices=["disable", "enable"]), + captive_portal_exempt=dict(required=False, type="str", choices=["disable", "enable"]), + block_notification=dict(required=False, type="str", choices=["disable", "enable"]), + av_profile=dict(required=False, type="str"), + auto_asic_offload=dict(required=False, type="str", choices=["disable", "enable"]), + auth_redirect_addr=dict(required=False, type="str"), + auth_path=dict(required=False, type="str", choices=["disable", "enable"]), + auth_cert=dict(required=False, type="str"), + application_list=dict(required=False, type="str"), + application=dict(required=False, type="str"), + app_group=dict(required=False, type="str"), + app_category=dict(required=False, type="str"), + action=dict(required=False, type="str", choices=["deny", "accept", "ipsec"]), + vpn_dst_node=dict(required=False, type="list"), + vpn_dst_node_host=dict(required=False, type="str"), + vpn_dst_node_seq=dict(required=False, type="str"), + vpn_dst_node_subnet=dict(required=False, type="str"), + vpn_src_node=dict(required=False, type="list"), + vpn_src_node_host=dict(required=False, type="str"), + vpn_src_node_seq=dict(required=False, type="str"), + vpn_src_node_subnet=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "package_name": module.params["package_name"], + "wsso": module.params["wsso"], + "webfilter-profile": module.params["webfilter_profile"], + "webcache-https": module.params["webcache_https"], + "webcache": module.params["webcache"], + "wccp": module.params["wccp"], + "wanopt-profile": module.params["wanopt_profile"], + "wanopt-peer": module.params["wanopt_peer"], + "wanopt-passive-opt": module.params["wanopt_passive_opt"], + "wanopt-detection": module.params["wanopt_detection"], + "wanopt": module.params["wanopt"], + "waf-profile": module.params["waf_profile"], + "vpntunnel": module.params["vpntunnel"], + "voip-profile": module.params["voip_profile"], + "vlan-filter": module.params["vlan_filter"], + "vlan-cos-rev": module.params["vlan_cos_rev"], + "vlan-cos-fwd": module.params["vlan_cos_fwd"], + "utm-status": module.params["utm_status"], + "users": module.params["users"], + "url-category": module.params["url_category"], + "traffic-shaper-reverse": module.params["traffic_shaper_reverse"], + "traffic-shaper": module.params["traffic_shaper"], + "timeout-send-rst": module.params["timeout_send_rst"], + "tcp-session-without-syn": module.params["tcp_session_without_syn"], + "tcp-mss-sender": module.params["tcp_mss_sender"], + "tcp-mss-receiver": module.params["tcp_mss_receiver"], + "status": module.params["status"], + "ssl-ssh-profile": module.params["ssl_ssh_profile"], + "ssl-mirror-intf": module.params["ssl_mirror_intf"], + "ssl-mirror": module.params["ssl_mirror"], + "ssh-filter-profile": module.params["ssh_filter_profile"], + "srcintf": module.params["srcintf"], + "srcaddr-negate": module.params["srcaddr_negate"], + "srcaddr": module.params["srcaddr"], + "spamfilter-profile": module.params["spamfilter_profile"], + "session-ttl": module.params["session_ttl"], + "service-negate": module.params["service_negate"], + "service": module.params["service"], + "send-deny-packet": module.params["send_deny_packet"], + "schedule-timeout": module.params["schedule_timeout"], + "schedule": module.params["schedule"], + "scan-botnet-connections": module.params["scan_botnet_connections"], + "rtp-nat": module.params["rtp_nat"], + "rtp-addr": module.params["rtp_addr"], + "rsso": module.params["rsso"], + "replacemsg-override-group": module.params["replacemsg_override_group"], + "redirect-url": module.params["redirect_url"], + "radius-mac-auth-bypass": module.params["radius_mac_auth_bypass"], + "profile-type": module.params["profile_type"], + "profile-protocol-options": module.params["profile_protocol_options"], + "profile-group": module.params["profile_group"], + "poolname": module.params["poolname"], + "policyid": module.params["policyid"], + "permit-stun-host": module.params["permit_stun_host"], + "permit-any-host": module.params["permit_any_host"], + "per-ip-shaper": module.params["per_ip_shaper"], + "outbound": module.params["outbound"], + "ntlm-guest": module.params["ntlm_guest"], + "ntlm-enabled-browsers": module.params["ntlm_enabled_browsers"], + "ntlm": module.params["ntlm"], + "np-acceleration": module.params["np_acceleration"], + "natoutbound": module.params["natoutbound"], + "natip": module.params["natip"], + "natinbound": module.params["natinbound"], + "nat": module.params["nat"], + "name": module.params["name"], + "mms-profile": module.params["mms_profile"], + "match-vip": module.params["match_vip"], + "logtraffic-start": module.params["logtraffic_start"], + "logtraffic": module.params["logtraffic"], + "learning-mode": module.params["learning_mode"], + "label": module.params["label"], + "ips-sensor": module.params["ips_sensor"], + "ippool": module.params["ippool"], + "internet-service-src-negate": module.params["internet_service_src_negate"], + "internet-service-src-id": module.params["internet_service_src_id"], + "internet-service-src-custom": module.params["internet_service_src_custom"], + "internet-service-src": module.params["internet_service_src"], + "internet-service-negate": module.params["internet_service_negate"], + "internet-service-id": module.params["internet_service_id"], + "internet-service-custom": module.params["internet_service_custom"], + "internet-service": module.params["internet_service"], + "inbound": module.params["inbound"], + "identity-based-route": module.params["identity_based_route"], + "icap-profile": module.params["icap_profile"], + "gtp-profile": module.params["gtp_profile"], + "groups": module.params["groups"], + "global-label": module.params["global_label"], + "fsso-agent-for-ntlm": module.params["fsso_agent_for_ntlm"], + "fsso": module.params["fsso"], + "fixedport": module.params["fixedport"], + "firewall-session-dirty": module.params["firewall_session_dirty"], + "dstintf": module.params["dstintf"], + "dstaddr-negate": module.params["dstaddr_negate"], + "dstaddr": module.params["dstaddr"], + "dsri": module.params["dsri"], + "dscp-value": module.params["dscp_value"], + "dscp-negate": module.params["dscp_negate"], + "dscp-match": module.params["dscp_match"], + "dnsfilter-profile": module.params["dnsfilter_profile"], + "dlp-sensor": module.params["dlp_sensor"], + "disclaimer": module.params["disclaimer"], + "diffservcode-rev": module.params["diffservcode_rev"], + "diffservcode-forward": module.params["diffservcode_forward"], + "diffserv-reverse": module.params["diffserv_reverse"], + "diffserv-forward": module.params["diffserv_forward"], + "devices": module.params["devices"], + "delay-tcp-npu-session": module.params["delay_tcp_npu_session"], + "custom-log-fields": module.params["custom_log_fields"], + "comments": module.params["comments"], + "capture-packet": module.params["capture_packet"], + "captive-portal-exempt": module.params["captive_portal_exempt"], + "block-notification": module.params["block_notification"], + "av-profile": module.params["av_profile"], + "auto-asic-offload": module.params["auto_asic_offload"], + "auth-redirect-addr": module.params["auth_redirect_addr"], + "auth-path": module.params["auth_path"], + "auth-cert": module.params["auth_cert"], + "application-list": module.params["application_list"], + "application": module.params["application"], + "app-group": module.params["app_group"], + "app-category": module.params["app_category"], + "action": module.params["action"], + "vpn_dst_node": { + "host": module.params["vpn_dst_node_host"], + "seq": module.params["vpn_dst_node_seq"], + "subnet": module.params["vpn_dst_node_subnet"], + }, + "vpn_src_node": { + "host": module.params["vpn_src_node_host"], + "seq": module.params["vpn_src_node_seq"], + "subnet": module.params["vpn_src_node_subnet"], + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['vpn_dst_node', 'vpn_src_node'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION + results = DEFAULT_RESULT_OBJ + try: + if paramgram["mode"] == "delete": + # WE NEED TO GET THE POLICY ID FROM THE NAME OF THE POLICY TO DELETE IT + url = '/pm/config/adom/{adom}/pkg/{pkg}/firewall' \ + '/policy/'.format(adom=paramgram["adom"], + pkg=paramgram["package_name"]) + datagram = { + "filter": ["name", "==", paramgram["name"]] + } + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + try: + if response[1][0]["policyid"]: + policy_id = response[1][0]["policyid"] + paramgram["policyid"] = policy_id + except BaseException: + fmgr.return_response(module=module, results=response, good_codes=[0, ], stop_on_success=True, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram), + msg="Couldn't find policy ID number for policy name specified.") + except Exception as err: + raise FMGBaseException(err) + + try: + results = fmgr_firewall_policy_modify(fmgr, paramgram) + if module.params["fail_on_missing_dependency"] == "disable": + fmgr.govern_response(module=module, results=results, good_codes=[0, -9998], + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + if module.params["fail_on_missing_dependency"] == "enable" and results[0] == -10131: + fmgr.govern_response(module=module, results=results, good_codes=[0, ], failed=True, skipped=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwpol_package.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwpol_package.py new file mode 100644 index 00000000..7b65393f --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_fwpol_package.py @@ -0,0 +1,479 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_fwpol_package +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manages FortiManager Firewall Policies Packages. +description: + - Manages FortiManager Firewall Policies Packages. Policy Packages contain one or more Firewall Policies/Rules and + are distritbuted via FortiManager to Fortigates. + - This module controls the creation/edit/delete/assign of these packages. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + choices: ['add', 'set', 'delete'] + default: add + + name: + description: + - Name of the FortiManager package or folder. + required: True + + object_type: + description: + - Are we managing packages or folders, or installing packages? + required: True + choices: ['pkg','folder','install'] + + package_folder: + description: + - Name of the folder you want to put the package into. + required: false + + central_nat: + description: + - Central NAT setting. + required: false + choices: ['enable', 'disable'] + default: disable + + fwpolicy_implicit_log: + description: + - Implicit Log setting for all IPv4 policies in package. + required: false + choices: ['enable', 'disable'] + default: disable + + fwpolicy6_implicit_log: + description: + - Implicit Log setting for all IPv6 policies in package. + required: false + choices: ['enable', 'disable'] + default: disable + + inspection_mode: + description: + - Inspection mode setting for the policies flow or proxy. + required: false + choices: ['flow', 'proxy'] + default: flow + + ngfw_mode: + description: + - NGFW mode setting for the policies flow or proxy. + required: false + choices: ['profile-based', 'policy-based'] + default: profile-based + + ssl_ssh_profile: + description: + - if policy-based ngfw-mode, refer to firewall ssl-ssh-profile. + required: false + + scope_members: + description: + - The devices or scope that you want to assign this policy package to. + required: false + + scope_members_vdom: + description: + - The members VDOM you want to assign the package to. + required: false + default: root + + parent_folder: + description: + - The parent folder name you want to add this object under. + required: false + +''' + + +EXAMPLES = ''' +- name: CREATE BASIC POLICY PACKAGE + community.fortios.fmgr_fwpol_package: + adom: "ansible" + mode: "add" + name: "testPackage" + object_type: "pkg" + +- name: ADD PACKAGE WITH TARGETS + community.fortios.fmgr_fwpol_package: + mode: "add" + adom: "ansible" + name: "ansibleTestPackage1" + object_type: "pkg" + inspection_mode: "flow" + ngfw_mode: "profile-based" + scope_members: "seattle-fgt02, seattle-fgt03" + +- name: ADD FOLDER + community.fortios.fmgr_fwpol_package: + mode: "add" + adom: "ansible" + name: "ansibleTestFolder1" + object_type: "folder" + +- name: ADD PACKAGE INTO PARENT FOLDER + community.fortios.fmgr_fwpol_package: + mode: "set" + adom: "ansible" + name: "ansibleTestPackage2" + object_type: "pkg" + parent_folder: "ansibleTestFolder1" + +- name: ADD FOLDER INTO PARENT FOLDER + community.fortios.fmgr_fwpol_package: + mode: "set" + adom: "ansible" + name: "ansibleTestFolder2" + object_type: "folder" + parent_folder: "ansibleTestFolder1" + +- name: INSTALL PACKAGE + community.fortios.fmgr_fwpol_package: + mode: "set" + adom: "ansible" + name: "ansibleTestPackage1" + object_type: "install" + scope_members: "seattle-fgt03, seattle-fgt02" + +- name: REMOVE PACKAGE + community.fortios.fmgr_fwpol_package: + mode: "delete" + adom: "ansible" + name: "ansibleTestPackage1" + object_type: "pkg" + +- name: REMOVE NESTED PACKAGE + community.fortios.fmgr_fwpol_package: + mode: "delete" + adom: "ansible" + name: "ansibleTestPackage2" + object_type: "pkg" + parent_folder: "ansibleTestFolder1" + +- name: REMOVE NESTED FOLDER + community.fortios.fmgr_fwpol_package: + mode: "delete" + adom: "ansible" + name: "ansibleTestFolder2" + object_type: "folder" + parent_folder: "ansibleTestFolder1" + +- name: REMOVE FOLDER + community.fortios.fmgr_fwpol_package: + mode: "delete" + adom: "ansible" + name: "ansibleTestFolder1" + object_type: "folder" +''' +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods + + +def fmgr_fwpol_package(fmgr, paramgram): + """ + This function will create FMGR Firewall Policy Packages, or delete them. It is also capable of assigning packages. + This function DOES NOT install the package. See the function fmgr_fwpol_package_install() + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + if paramgram["mode"] in ['set', 'add']: + url = '/pm/pkg/adom/{adom}'.format(adom=paramgram["adom"]) + members_list = [] + + # CHECK FOR SCOPE MEMBERS AND CREATE THAT DICT + if paramgram["scope_members"] is not None: + members = FMGRCommon.split_comma_strings_into_lists(paramgram["scope_members"]) + for member in members: + scope_dict = { + "name": member, + "vdom": paramgram["scope_members_vdom"], + } + members_list.append(scope_dict) + + # IF PARENT FOLDER IS NOT DEFINED + if paramgram["parent_folder"] is None: + datagram = { + "type": paramgram["object_type"], + "name": paramgram["name"], + "scope member": members_list, + "package settings": { + "central-nat": paramgram["central-nat"], + "fwpolicy-implicit-log": paramgram["fwpolicy-implicit-log"], + "fwpolicy6-implicit-log": paramgram["fwpolicy6-implicit-log"], + "inspection-mode": paramgram["inspection-mode"], + "ngfw-mode": paramgram["ngfw-mode"], + } + } + + if paramgram["ngfw-mode"] == "policy-based" and paramgram["ssl-ssh-profile"] is not None: + datagram["package settings"]["ssl-ssh-profile"] = paramgram["ssl-ssh-profile"] + + # IF PARENT FOLDER IS DEFINED + if paramgram["parent_folder"] is not None: + datagram = { + "type": "folder", + "name": paramgram["parent_folder"], + "subobj": [{ + "name": paramgram["name"], + "scope member": members_list, + "type": "pkg", + "package settings": { + "central-nat": paramgram["central-nat"], + "fwpolicy-implicit-log": paramgram["fwpolicy-implicit-log"], + "fwpolicy6-implicit-log": paramgram["fwpolicy6-implicit-log"], + "inspection-mode": paramgram["inspection-mode"], + "ngfw-mode": paramgram["ngfw-mode"], + } + }] + } + + # NORMAL DELETE NO PARENT + if paramgram["mode"] == "delete" and paramgram["parent_folder"] is None: + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/pkg/adom/{adom}/{name}'.format(adom=paramgram["adom"], name=paramgram["name"]) + + # DELETE WITH PARENT + if paramgram["mode"] == "delete" and paramgram["parent_folder"] is not None: + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/pkg/adom/{adom}/{parent_folder}/{name}'.format(adom=paramgram["adom"], + name=paramgram["name"], + parent_folder=paramgram["parent_folder"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def fmgr_fwpol_package_folder(fmgr, paramgram): + """ + This function will create folders for firewall packages. It can create down to two levels deep. + We haven't yet tested for any more layers below two levels. + parent_folders for multiple levels may need to defined as "level1/level2/level3" for the URL parameters and such. + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + if paramgram["mode"] in ['set', 'add']: + url = '/pm/pkg/adom/{adom}'.format(adom=paramgram["adom"]) + # IF PARENT FOLDER IS NOT DEFINED + if paramgram["parent_folder"] is None: + datagram = { + "type": paramgram["object_type"], + "name": paramgram["name"], + } + + # IF PARENT FOLDER IS DEFINED + if paramgram["parent_folder"] is not None: + datagram = { + "type": paramgram["object_type"], + "name": paramgram["parent_folder"], + "subobj": [{ + "name": paramgram["name"], + "type": paramgram["object_type"], + + }] + } + # NORMAL DELETE NO PARENT + if paramgram["mode"] == "delete" and paramgram["parent_folder"] is None: + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/pkg/adom/{adom}/{name}'.format(adom=paramgram["adom"], name=paramgram["name"]) + + # DELETE WITH PARENT + if paramgram["mode"] == "delete" and paramgram["parent_folder"] is not None: + datagram = { + "name": paramgram["name"] + } + # SET DELETE URL + url = '/pm/pkg/adom/{adom}/{parent_folder}/{name}'.format(adom=paramgram["adom"], + name=paramgram["name"], + parent_folder=paramgram["parent_folder"]) + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +def fmgr_fwpol_package_install(fmgr, paramgram): + """ + This method/function installs FMGR FW Policy Packages to the scope members defined in the playbook. + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + # INIT BLANK MEMBERS LIST + members_list = [] + # USE THE PARSE CSV FUNCTION TO GET A LIST FORMAT OF THE MEMBERS + members = FMGRCommon.split_comma_strings_into_lists(paramgram["scope_members"]) + # USE THAT LIST TO BUILD THE DICTIONARIES NEEDED, AND ADD TO THE BLANK MEMBERS LIST + for member in members: + scope_dict = { + "name": member, + "vdom": paramgram["scope_members_vdom"], + } + members_list.append(scope_dict) + # THEN FOR THE DATAGRAM, USING THE MEMBERS LIST CREATED ABOVE + datagram = { + "adom": paramgram["adom"], + "pkg": paramgram["name"], + "scope": members_list + } + # EXECUTE THE INSTALL REQUEST + url = '/securityconsole/install/package' + response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "set", "delete"], type="str", default="add"), + + name=dict(required=False, type="str"), + object_type=dict(required=True, type="str", choices=['pkg', 'folder', 'install']), + package_folder=dict(required=False, type="str"), + central_nat=dict(required=False, type="str", default="disable", choices=['enable', 'disable']), + fwpolicy_implicit_log=dict(required=False, type="str", default="disable", choices=['enable', 'disable']), + fwpolicy6_implicit_log=dict(required=False, type="str", default="disable", choices=['enable', 'disable']), + inspection_mode=dict(required=False, type="str", default="flow", choices=['flow', 'proxy']), + ngfw_mode=dict(required=False, type="str", default="profile-based", choices=['profile-based', 'policy-based']), + ssl_ssh_profile=dict(required=False, type="str"), + scope_members=dict(required=False, type="str"), + scope_members_vdom=dict(required=False, type="str", default="root"), + parent_folder=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE DATAGRAM + paramgram = { + "adom": module.params["adom"], + "name": module.params["name"], + "mode": module.params["mode"], + "object_type": module.params["object_type"], + "package-folder": module.params["package_folder"], + "central-nat": module.params["central_nat"], + "fwpolicy-implicit-log": module.params["fwpolicy_implicit_log"], + "fwpolicy6-implicit-log": module.params["fwpolicy6_implicit_log"], + "inspection-mode": module.params["inspection_mode"], + "ngfw-mode": module.params["ngfw_mode"], + "ssl-ssh-profile": module.params["ssl_ssh_profile"], + "scope_members": module.params["scope_members"], + "scope_members_vdom": module.params["scope_members_vdom"], + "parent_folder": module.params["parent_folder"], + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION + results = DEFAULT_RESULT_OBJ + + try: + if paramgram["object_type"] == "pkg": + results = fmgr_fwpol_package(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF THE object_type IS FOLDER LETS RUN THAT METHOD + if paramgram["object_type"] == "folder": + results = fmgr_fwpol_package_folder(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF THE object_type IS INSTALL AND NEEDED PARAMETERS ARE DEFINED INSTALL THE PACKAGE + if paramgram["scope_members"] is not None and paramgram["name"] is not None and\ + paramgram["object_type"] == "install": + results = fmgr_fwpol_package_install(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_ha.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_ha.py new file mode 100644 index 00000000..e24f1146 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_ha.py @@ -0,0 +1,349 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_ha +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manages the High-Availability State of FortiManager Clusters and Nodes. +description: Change HA state or settings of FortiManager nodes (Standalone/Master/Slave). + +options: + fmgr_ha_mode: + description: + - Sets the role of the FortiManager host for HA. + required: false + choices: ["standalone", "master", "slave"] + + fmgr_ha_peer_ipv4: + description: + - Sets the IPv4 address of a HA peer. + required: false + + fmgr_ha_peer_ipv6: + description: + - Sets the IPv6 address of a HA peer. + required: false + + fmgr_ha_peer_sn: + description: + - Sets the HA Peer Serial Number. + required: false + + fmgr_ha_peer_status: + description: + - Sets the peer status to enable or disable. + required: false + choices: ["enable", "disable"] + + fmgr_ha_cluster_pw: + description: + - Sets the password for the HA cluster. Only required once. System remembers between HA mode switches. + required: false + + fmgr_ha_cluster_id: + description: + - Sets the ID number of the HA cluster. Defaults to 1. + required: false + default: 1 + + fmgr_ha_hb_threshold: + description: + - Sets heartbeat lost threshold (1-255). + required: false + default: 3 + + fmgr_ha_hb_interval: + description: + - Sets the heartbeat interval (1-255). + required: false + default: 5 + + fmgr_ha_file_quota: + description: + - Sets the File quota in MB (2048-20480). + required: false + default: 4096 +''' + + +EXAMPLES = ''' +- name: SET FORTIMANAGER HA NODE TO MASTER + community.fortios.fmgr_ha: + fmgr_ha_mode: "master" + fmgr_ha_cluster_pw: "fortinet" + fmgr_ha_cluster_id: "1" + +- name: SET FORTIMANAGER HA NODE TO SLAVE + community.fortios.fmgr_ha: + fmgr_ha_mode: "slave" + fmgr_ha_cluster_pw: "fortinet" + fmgr_ha_cluster_id: "1" + +- name: SET FORTIMANAGER HA NODE TO STANDALONE + community.fortios.fmgr_ha: + fmgr_ha_mode: "standalone" + +- name: ADD FORTIMANAGER HA PEER + community.fortios.fmgr_ha: + fmgr_ha_peer_ipv4: "192.168.1.254" + fmgr_ha_peer_sn: "FMG-VM1234567890" + fmgr_ha_peer_status: "enable" + +- name: CREATE CLUSTER ON MASTER + community.fortios.fmgr_ha: + fmgr_ha_mode: "master" + fmgr_ha_cluster_pw: "fortinet" + fmgr_ha_cluster_id: "1" + fmgr_ha_hb_threshold: "10" + fmgr_ha_hb_interval: "15" + fmgr_ha_file_quota: "2048" +''' +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def fmgr_set_ha_mode(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + if paramgram["fmgr_ha_cluster_pw"] is not None and str(paramgram["fmgr_ha_mode"].lower()) != "standalone": + datagram = { + "mode": paramgram["fmgr_ha_mode"], + "file-quota": paramgram["fmgr_ha_file_quota"], + "hb-interval": paramgram["fmgr_ha_hb_interval"], + "hb-lost-threshold": paramgram["fmgr_ha_hb_threshold"], + "password": paramgram["fmgr_ha_cluster_pw"], + "clusterid": paramgram["fmgr_ha_cluster_id"] + } + elif str(paramgram["fmgr_ha_mode"].lower()) == "standalone": + datagram = { + "mode": paramgram["fmgr_ha_mode"], + "file-quota": paramgram["fmgr_ha_file_quota"], + "hb-interval": paramgram["fmgr_ha_hb_interval"], + "hb-lost-threshold": paramgram["fmgr_ha_hb_threshold"], + "clusterid": paramgram["fmgr_ha_cluster_id"] + } + + url = '/cli/global/system/ha' + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + return response + + +def fmgr_get_ha_peer_list(fmgr): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + + datagram = {} + paramgram = {} + + url = '/cli/global/system/ha/peer/' + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + return response + + +def fmgr_set_ha_peer(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + datagram = { + "ip": paramgram["fmgr_ha_peer_ipv4"], + "ip6": paramgram["fmgr_ha_peer_ipv6"], + "serial-number": paramgram["fmgr_ha_peer_sn"], + "status": paramgram["fmgr_ha_peer_status"], + "id": paramgram["peer_id"] + } + + url = '/cli/global/system/ha/peer/' + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + return response + + +def main(): + argument_spec = dict( + fmgr_ha_mode=dict(required=False, type="str", choices=["standalone", "master", "slave"]), + fmgr_ha_cluster_pw=dict(required=False, type="str", no_log=True), + fmgr_ha_peer_status=dict(required=False, type="str", choices=["enable", "disable"]), + fmgr_ha_peer_sn=dict(required=False, type="str"), + fmgr_ha_peer_ipv4=dict(required=False, type="str"), + fmgr_ha_peer_ipv6=dict(required=False, type="str"), + fmgr_ha_hb_threshold=dict(required=False, type="int", default=3), + fmgr_ha_hb_interval=dict(required=False, type="int", default=5), + fmgr_ha_file_quota=dict(required=False, type="int", default=4096), + fmgr_ha_cluster_id=dict(required=False, type="int", default=1) + ) + + required_if = [ + ['fmgr_ha_peer_ipv4', 'present', ['fmgr_ha_peer_sn', 'fmgr_ha_peer_status']], + ['fmgr_ha_peer_ipv6', 'present', ['fmgr_ha_peer_sn', 'fmgr_ha_peer_status']], + ['fmgr_ha_mode', 'master', ['fmgr_ha_cluster_pw', 'fmgr_ha_cluster_id']], + ['fmgr_ha_mode', 'slave', ['fmgr_ha_cluster_pw', 'fmgr_ha_cluster_id']], + ] + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_if=required_if) + paramgram = { + "fmgr_ha_mode": module.params["fmgr_ha_mode"], + "fmgr_ha_cluster_pw": module.params["fmgr_ha_cluster_pw"], + "fmgr_ha_peer_status": module.params["fmgr_ha_peer_status"], + "fmgr_ha_peer_sn": module.params["fmgr_ha_peer_sn"], + "fmgr_ha_peer_ipv4": module.params["fmgr_ha_peer_ipv4"], + "fmgr_ha_peer_ipv6": module.params["fmgr_ha_peer_ipv6"], + "fmgr_ha_hb_threshold": module.params["fmgr_ha_hb_threshold"], + "fmgr_ha_hb_interval": module.params["fmgr_ha_hb_interval"], + "fmgr_ha_file_quota": module.params["fmgr_ha_file_quota"], + "fmgr_ha_cluster_id": module.params["fmgr_ha_cluster_id"], + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + # INIT FLAGS AND COUNTERS + get_ha_peers = 0 + results = DEFAULT_RESULT_OBJ + try: + if any(v is not None for v in (paramgram["fmgr_ha_peer_sn"], paramgram["fmgr_ha_peer_ipv4"], + paramgram["fmgr_ha_peer_ipv6"], paramgram["fmgr_ha_peer_status"])): + get_ha_peers = 1 + except Exception as err: + raise FMGBaseException(err) + try: + # IF HA MODE IS NOT NULL, SWITCH THAT + if paramgram["fmgr_ha_mode"] is not None: + if (str.lower(paramgram["fmgr_ha_mode"]) != "standalone" and paramgram["fmgr_ha_cluster_pw"] is not None)\ + or str.lower(paramgram["fmgr_ha_mode"]) == "standalone": + results = fmgr_set_ha_mode(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, stop_on_success=False, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + elif str.lower(paramgram["fmgr_ha_mode"]) != "standalone" and\ + paramgram["fmgr_ha_mode"] is not None and\ + paramgram["fmgr_ha_cluster_pw"] is None: + module.exit_json(msg="If setting HA Mode of MASTER or SLAVE, you must specify a cluster password") + + except Exception as err: + raise FMGBaseException(err) + # IF GET_HA_PEERS IS ENABLED, LETS PROCESS THE PEERS + try: + if get_ha_peers == 1: + # GET THE CURRENT LIST OF PEERS FROM THE NODE + peers = fmgr_get_ha_peer_list(fmgr) + # GET LENGTH OF RETURNED PEERS LIST AND ADD ONE FOR THE NEXT ID + paramgram["next_peer_id"] = len(peers[1]) + 1 + # SET THE ACTUAL NUMBER OF PEERS + num_of_peers = len(peers[1]) + # SET THE PEER ID FOR DISABLE METHOD + paramgram["peer_id"] = len(peers) - 1 + # SET THE PEER LOOPCOUNT TO 1 TO START THE LOOP + peer_loopcount = 1 + + # LOOP THROUGH PEERS TO FIND THE SERIAL NUMBER MATCH TO GET THE RIGHT PEER ID + # IDEA BEING WE DON'T WANT TO SUBMIT A BAD peer_id THAT DOESN'T JIVE WITH CURRENT DB ON FMG + # SO LETS SEARCH FOR IT, AND IF WE FIND IT, WE WILL CHANGE THE PEER ID VARIABLES TO MATCH + # IF NOT FOUND, LIFE GOES ON AND WE ASSUME THAT WE'RE ADDING A PEER + # AT WHICH POINT THE next_peer_id VARIABLE WILL HAVE THE RIGHT PRIMARY KEY + + if paramgram["fmgr_ha_peer_sn"] is not None: + while peer_loopcount <= num_of_peers: + # GET THE SERIAL NUMBER FOR CURRENT PEER IN LOOP TO COMPARE TO SN IN PLAYBOOK + try: + sn_compare = peers[1][peer_loopcount - 1]["serial-number"] + # IF THE SN IN THE PEERS MATCHES THE PLAYBOOK SN, SET THE IDS + if sn_compare == paramgram["fmgr_ha_peer_sn"]: + paramgram["peer_id"] = peer_loopcount + paramgram["next_peer_id"] = paramgram["peer_id"] + except Exception as err: + raise FMGBaseException(err) + # ADVANCE THE LOOP AND REPEAT UNTIL DONE + peer_loopcount += 1 + + # IF THE PEER STATUS ISN'T IN THE PLAYBOOK, ASSUME ITS ENABLE + if paramgram["fmgr_ha_peer_status"] is None: + paramgram["fmgr_ha_peer_status"] = "enable" + + # IF THE PEER STATUS IS ENABLE, USE THE next_peer_id IN THE API CALL FOR THE ID + if paramgram["fmgr_ha_peer_status"] == "enable": + results = fmgr_set_ha_peer(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, stop_on_success=True, + ansible_facts=fmgr.construct_ansible_facts(results, + module.params, paramgram)) + + # IF THE PEER STATUS IS DISABLE, WE HAVE TO HANDLE THAT A BIT DIFFERENTLY + # JUST USING TWO DIFFERENT peer_id 's HERE + if paramgram["fmgr_ha_peer_status"] == "disable": + results = fmgr_set_ha_peer(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, stop_on_success=True, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_provisioning.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_provisioning.py new file mode 100644 index 00000000..da499cbe --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_provisioning.py @@ -0,0 +1,360 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_provisioning +author: Andrew Welsh (@Ghilli3) +short_description: Provision devices via FortiMananger +description: + - Add model devices on the FortiManager using jsonrpc API and have them pre-configured, + so when central management is configured, the configuration is pushed down to the + registering devices + +options: + adom: + description: + - The administrative domain (admon) the configuration belongs to + required: true + vdom: + description: + - The virtual domain (vdom) the configuration belongs to + host: + description: + - The FortiManager's Address. + required: true + username: + description: + - The username to log into the FortiManager + required: true + password: + description: + - The password associated with the username account. + required: false + + policy_package: + description: + - The name of the policy package to be assigned to the device. + required: True + name: + description: + - The name of the device to be provisioned. + required: True + group: + description: + - The name of the device group the provisioned device can belong to. + required: False + serial: + description: + - The serial number of the device that will be provisioned. + required: True + platform: + description: + - The platform of the device, such as model number or VM. + required: True + description: + description: + - Description of the device to be provisioned. + required: False + os_version: + description: + - The Fortinet OS version to be used for the device, such as 5.0 or 6.0. + required: True + minor_release: + description: + - The minor release number such as 6.X.1, as X being the minor release. + required: False + patch_release: + description: + - The patch release number such as 6.0.X, as X being the patch release. + required: False + os_type: + description: + - The Fortinet OS type to be pushed to the device, such as 'FOS' for FortiOS. + required: True +''' + +EXAMPLES = ''' +- name: Create FGT1 Model Device + community.fortios.fmgr_provisioning: + host: "{{ inventory_hostname }}" + username: "{{ username }}" + password: "{{ password }}" + adom: "root" + vdom: "root" + policy_package: "default" + name: "FGT1" + group: "Ansible" + serial: "FGVM000000117994" + platform: "FortiGate-VM64" + description: "Provisioned by Ansible" + os_version: '6.0' + minor_release: 0 + patch_release: 0 + os_type: 'fos' + + +- name: Create FGT2 Model Device + community.fortios.fmgr_provisioning: + host: "{{ inventory_hostname }}" + username: "{{ username }}" + password: "{{ password }}" + adom: "root" + vdom: "root" + policy_package: "test_pp" + name: "FGT2" + group: "Ansible" + serial: "FGVM000000117992" + platform: "FortiGate-VM64" + description: "Provisioned by Ansible" + os_version: '5.0' + minor_release: 6 + patch_release: 0 + os_type: 'fos' + +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import AnsibleFortiManager + +# check for pyFMG lib +try: + from pyFMG.fortimgr import FortiManager + HAS_PYFMGR = True +except ImportError: + HAS_PYFMGR = False + + +def dev_group_exists(fmg, dev_grp_name, adom): + datagram = { + 'adom': adom, + 'name': dev_grp_name, + } + + url = '/dvmdb/adom/{adom}/group/{dev_grp_name}'.format(adom=adom, dev_grp_name=dev_grp_name) + response = fmg.get(url, datagram) + return response + + +def prov_template_exists(fmg, prov_template, adom, vdom): + datagram = { + 'name': prov_template, + 'adom': adom, + } + + url = '/pm/devprof/adom/{adom}/devprof/{name}'.format(adom=adom, name=prov_template) + response = fmg.get(url, datagram) + return response + + +def create_model_device(fmg, name, serial, group, platform, os_version, + os_type, minor_release, patch_release=0, adom='root'): + datagram = { + 'adom': adom, + 'flags': ['create_task', 'nonblocking'], + 'groups': [{'name': group, 'vdom': 'root'}], + 'device': { + 'mr': minor_release, + 'name': name, + 'sn': serial, + 'mgmt_mode': 'fmg', + 'device action': 'add_model', + 'platform_str': platform, + 'os_ver': os_version, + 'os_type': os_type, + 'patch': patch_release, + 'desc': 'Provisioned by Ansible', + } + } + + url = '/dvm/cmd/add/device' + response = fmg.execute(url, datagram) + return response + + +def update_flags(fmg, name): + datagram = { + 'flags': ['is_model', 'linked_to_model'] + } + url = 'dvmdb/device/{name}'.format(name=name) + response = fmg.update(url, datagram) + return response + + +def assign_provision_template(fmg, template, adom, target): + datagram = { + 'name': template, + 'type': 'devprof', + 'description': 'Provisioned by Ansible', + 'scope member': [{'name': target}] + } + url = "/pm/devprof/adom/{adom}".format(adom=adom) + response = fmg.update(url, datagram) + return response + + +def set_devprof_scope(self, provisioning_template, adom, provision_targets): + """ + GET the DevProf (check to see if exists) + """ + fields = dict() + targets = [] + fields["name"] = provisioning_template + fields["type"] = "devprof" + fields["description"] = "CreatedByAnsible" + + for target in provision_targets.strip().split(","): + # split the host on the space to get the mask out + new_target = {"name": target} + targets.append(new_target) + + fields["scope member"] = targets + + body = {"method": "set", "params": [{"url": "/pm/devprof/adom/{adom}".format(adom=adom), + "data": fields, "session": self.session}]} + response = self.make_request(body).json() + return response + + +def assign_dev_grp(fmg, grp_name, device_name, vdom, adom): + datagram = { + 'name': device_name, + 'vdom': vdom, + } + url = "/dvmdb/adom/{adom}/group/{grp_name}/object member".format(adom=adom, grp_name=grp_name) + response = fmg.set(url, datagram) + return response + + +def update_install_target(fmg, device, pp='default', vdom='root', adom='root'): + datagram = { + 'scope member': [{'name': device, 'vdom': vdom}], + 'type': 'pkg' + } + url = '/pm/pkg/adom/{adom}/{pkg_name}'.format(adom=adom, pkg_name=pp) + response = fmg.update(url, datagram) + return response + + +def install_pp(fmg, device, pp='default', vdom='root', adom='root'): + datagram = { + 'adom': adom, + 'flags': 'nonblocking', + 'pkg': pp, + 'scope': [{'name': device, 'vdom': vdom}], + } + url = 'securityconsole/install/package' + response = fmg.execute(url, datagram) + return response + + +def main(): + + argument_spec = dict( + adom=dict(required=False, type="str"), + vdom=dict(required=False, type="str"), + host=dict(required=True, type="str"), + password=dict(fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]), no_log=True), + username=dict(fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"]), no_log=True), + + policy_package=dict(required=False, type="str"), + name=dict(required=False, type="str"), + group=dict(required=False, type="str"), + serial=dict(required=True, type="str"), + platform=dict(required=True, type="str"), + description=dict(required=False, type="str"), + os_version=dict(required=True, type="str"), + minor_release=dict(required=False, type="str"), + patch_release=dict(required=False, type="str"), + os_type=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec, supports_check_mode=True, ) + + # check if params are set + if module.params["host"] is None or module.params["username"] is None: + module.fail_json(msg="Host and username are required for connection") + + # check if login failed + fmg = AnsibleFortiManager(module, module.params["host"], module.params["username"], module.params["password"]) + response = fmg.login() + + if "FortiManager instance connnected" not in str(response): + module.fail_json(msg="Connection to FortiManager Failed") + else: + + if module.params["policy_package"] is None: + module.params["policy_package"] = 'default' + if module.params["adom"] is None: + module.params["adom"] = 'root' + if module.params["vdom"] is None: + module.params["vdom"] = 'root' + if module.params["platform"] is None: + module.params["platform"] = 'FortiGate-VM64' + if module.params["os_type"] is None: + module.params["os_type"] = 'fos' + + results = create_model_device(fmg, + module.params["name"], + module.params["serial"], + module.params["group"], + module.params["platform"], + module.params["os_ver"], + module.params["os_type"], + module.params["minor_release"], + module.params["patch_release"], + module.params["adom"]) + if results[0] != 0: + module.fail_json(msg="Create model failed", **results) + + results = update_flags(fmg, module.params["name"]) + if results[0] != 0: + module.fail_json(msg="Update device flags failed", **results) + + # results = assign_dev_grp(fmg, 'Ansible', 'FGVM000000117992', 'root', 'root') + # if not results[0] == 0: + # module.fail_json(msg="Setting device group failed", **results) + + results = update_install_target(fmg, module.params["name"], module.params["policy_package"]) + if results[0] != 0: + module.fail_json(msg="Adding device target to package failed", **results) + + results = install_pp(fmg, module.params["name"], module.params["policy_package"]) + if results[0] != 0: + module.fail_json(msg="Installing policy package failed", **results) + + fmg.logout() + + # results is returned as a tuple + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_query.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_query.py new file mode 100644 index 00000000..1ceb7dbb --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_query.py @@ -0,0 +1,424 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_query +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: Luke Weighall (@lweighall) +short_description: Query FortiManager data objects for use in Ansible workflows. +description: + - Provides information on data objects within FortiManager so that playbooks can perform conditionals. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + object: + description: + - The data object we wish to query (device, package, rule, etc). Will expand choices as improves. + required: true + choices: + - device + - cluster_nodes + - task + - custom + + custom_endpoint: + description: + - ADVANCED USERS ONLY! REQUIRES KNOWLEDGE OF FMGR JSON API! + - The HTTP Endpoint on FortiManager you wish to GET from. + required: false + + custom_dict: + description: + - ADVANCED USERS ONLY! REQUIRES KNOWLEDGE OF FMGR JSON API! + - DICTIONARY JSON FORMAT ONLY -- Custom dictionary/datagram to send to the endpoint. + required: false + + device_ip: + description: + - The IP of the device you want to query. + required: false + + device_unique_name: + description: + - The desired "friendly" name of the device you want to query. + required: false + + device_serial: + description: + - The serial number of the device you want to query. + required: false + + task_id: + description: + - The ID of the task you wish to query status on. If left blank and object = 'task' a list of tasks are returned. + required: false + + nodes: + description: + - A LIST of firewalls in the cluster you want to verify i.e. ["firewall_A","firewall_B"]. + required: false +''' + + +EXAMPLES = ''' +- name: QUERY FORTIGATE DEVICE BY IP + community.fortios.fmgr_query: + object: "device" + adom: "ansible" + device_ip: "10.7.220.41" + +- name: QUERY FORTIGATE DEVICE BY SERIAL + community.fortios.fmgr_query: + adom: "ansible" + object: "device" + device_serial: "FGVM000000117992" + +- name: QUERY FORTIGATE DEVICE BY FRIENDLY NAME + community.fortios.fmgr_query: + adom: "ansible" + object: "device" + device_unique_name: "ansible-fgt01" + +- name: VERIFY CLUSTER MEMBERS AND STATUS + community.fortios.fmgr_query: + adom: "ansible" + object: "cluster_nodes" + device_unique_name: "fgt-cluster01" + nodes: ["ansible-fgt01", "ansible-fgt02", "ansible-fgt03"] + +- name: GET STATUS OF TASK ID + community.fortios.fmgr_query: + adom: "ansible" + object: "task" + task_id: "3" + +- name: USE CUSTOM TYPE TO QUERY AVAILABLE SCRIPTS + community.fortios.fmgr_query: + adom: "ansible" + object: "custom" + custom_endpoint: "/dvmdb/adom/ansible/script" + custom_dict: { "type": "cli" } +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def fmgr_get_custom(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # IF THE CUSTOM DICTIONARY (OFTEN CONTAINING FILTERS) IS DEFINED CREATED THAT + if paramgram["custom_dict"] is not None: + datagram = paramgram["custom_dict"] + else: + datagram = dict() + + # SET THE CUSTOM ENDPOINT PROVIDED + url = paramgram["custom_endpoint"] + # MAKE THE CALL AND RETURN RESULTS + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + return response + + +def fmgr_get_task_status(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # IF THE TASK_ID IS DEFINED, THEN GET THAT SPECIFIC TASK + # OTHERWISE, GET ALL RECENT TASKS IN A LIST + if paramgram["task_id"] is not None: + + datagram = { + "adom": paramgram["adom"] + } + url = '/task/task/{task_id}'.format(task_id=paramgram["task_id"]) + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + else: + datagram = { + "adom": paramgram["adom"] + } + url = '/task/task' + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + return response + + +def fmgr_get_device(fmgr, paramgram): + """ + This method is used to get information on devices. This will not work on HA_SLAVE nodes, only top level devices. + Such as cluster objects and standalone devices. + + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + # FIRST TRY TO RUN AN UPDATE ON THE DEVICE + # RUN A QUICK CLUSTER REFRESH/UPDATE ATTEMPT TO ENSURE WE'RE GETTING THE LATEST INFORMOATION + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + update_url = '/dvm/cmd/update/device' + update_dict = { + "adom": paramgram['adom'], + "device": paramgram['device_unique_name'], + "flags": "create_task" + } + # DO THE UPDATE CALL + fmgr.process_request(update_url, update_dict, FMGRMethods.EXEC) + + # SET THE URL + url = '/dvmdb/adom/{adom}/device'.format(adom=paramgram["adom"]) + device_found = 0 + response = [] + + # TRY TO FIND IT FIRST BY SERIAL NUMBER + if paramgram["device_serial"] is not None: + datagram = { + "filter": ["sn", "==", paramgram["device_serial"]] + } + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + if len(response[1]) >= 0: + device_found = 1 + + # CHECK IF ANYTHING WAS RETURNED, IF NOT TRY DEVICE NAME PARAMETER + if device_found == 0 and paramgram["device_unique_name"] is not None: + datagram = { + "filter": ["name", "==", paramgram["device_unique_name"]] + } + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + if len(response[1]) >= 0: + device_found = 1 + + # CHECK IF ANYTHING WAS RETURNED, IF NOT TRY DEVICE IP ADDRESS + if device_found == 0 and paramgram["device_ip"] is not None: + datagram = { + "filter": ["ip", "==", paramgram["device_ip"]] + } + response = fmgr.process_request(url, datagram, FMGRMethods.GET) + if len(response[1]) >= 0: + device_found = 1 + + return response + + +def fmgr_get_cluster_nodes(fmgr, paramgram): + """ + This method is used to get information on devices. This WILL work on HA_SLAVE nodes, but NOT top level standalone + devices. + Such as cluster objects and standalone devices. + + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + # USE THE DEVICE METHOD TO GET THE CLUSTER INFORMATION SO WE CAN SEE THE HA_SLAVE NODES + response = fmgr_get_device(fmgr, paramgram) + # CHECK FOR HA_SLAVE NODES, IF CLUSTER IS MISSING COMPLETELY THEN QUIT + try: + returned_nodes = response[1][0]["ha_slave"] + num_of_nodes = len(returned_nodes) + except Exception: + error_msg = {"cluster_status": "MISSING"} + return error_msg + + # INIT LOOP RESOURCES + loop_count = 0 + good_nodes = [] + expected_nodes = list(paramgram["nodes"]) + missing_nodes = list(paramgram["nodes"]) + bad_status_nodes = [] + + # LOOP THROUGH THE NODES AND GET THEIR STATUS TO BUILD THE RETURN JSON OBJECT + # WE'RE ALSO CHECKING THE NODES IF THEY ARE BAD STATUS, OR PLAIN MISSING + while loop_count < num_of_nodes: + node_append = { + "node_name": returned_nodes[loop_count]["name"], + "node_serial": returned_nodes[loop_count]["sn"], + "node_parent": returned_nodes[loop_count]["did"], + "node_status": returned_nodes[loop_count]["status"], + } + # IF THE NODE IS IN THE EXPECTED NODES LIST AND WORKING THEN ADD IT TO GOOD NODES LIST + if node_append["node_name"] in expected_nodes and node_append["node_status"] == 1: + good_nodes.append(node_append["node_name"]) + # IF THE NODE IS IN THE EXPECTED NODES LIST BUT NOT WORKING THEN ADDED IT TO BAD_STATUS_NODES + # IF THE NODE STATUS IS NOT 1 THEN ITS BAD + if node_append["node_name"] in expected_nodes and node_append["node_status"] != 1: + bad_status_nodes.append(node_append["node_name"]) + # REMOVE THE NODE FROM MISSING NODES LIST IF NOTHING IS WRONG WITH NODE -- LEAVING US A LIST OF + # NOT WORKING NODES + missing_nodes.remove(node_append["node_name"]) + loop_count += 1 + + # BUILD RETURN OBJECT FROM NODE LISTS + nodes = { + "good_nodes": good_nodes, + "expected_nodes": expected_nodes, + "missing_nodes": missing_nodes, + "bad_nodes": bad_status_nodes, + "query_status": "good", + } + if len(nodes["good_nodes"]) == len(nodes["expected_nodes"]): + nodes["cluster_status"] = "OK" + else: + nodes["cluster_status"] = "NOT-COMPLIANT" + return nodes + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + object=dict(required=True, type="str", choices=["device", "cluster_nodes", "task", "custom"]), + custom_endpoint=dict(required=False, type="str"), + custom_dict=dict(required=False, type="dict"), + device_ip=dict(required=False, type="str"), + device_unique_name=dict(required=False, type="str"), + device_serial=dict(required=False, type="str"), + nodes=dict(required=False, type="list"), + task_id=dict(required=False, type="str") + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + paramgram = { + "adom": module.params["adom"], + "object": module.params["object"], + "device_ip": module.params["device_ip"], + "device_unique_name": module.params["device_unique_name"], + "device_serial": module.params["device_serial"], + "nodes": module.params["nodes"], + "task_id": module.params["task_id"], + "custom_endpoint": module.params["custom_endpoint"], + "custom_dict": module.params["custom_dict"] + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + + try: + # IF OBJECT IS DEVICE + if paramgram["object"] == "device" and any(v is not None for v in [paramgram["device_unique_name"], + paramgram["device_serial"], + paramgram["device_ip"]]): + results = fmgr_get_device(fmgr, paramgram) + if results[0] not in [0]: + module.fail_json(msg="Device query failed!") + elif len(results[1]) == 0: + module.exit_json(msg="Device NOT FOUND!") + else: + module.exit_json(msg="Device Found", **results[1][0]) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF OBJECT IS CLUSTER_NODES + if paramgram["object"] == "cluster_nodes" and paramgram["nodes"] is not None: + results = fmgr_get_cluster_nodes(fmgr, paramgram) + if results["cluster_status"] == "MISSING": + module.exit_json(msg="No cluster device found!", **results) + elif results["query_status"] == "good": + module.exit_json(msg="Cluster Found - Showing Nodes", **results) + elif results is None: + module.fail_json(msg="Query FAILED -- Check module or playbook syntax") + except Exception as err: + raise FMGBaseException(err) + + try: + # IF OBJECT IS TASK + if paramgram["object"] == "task": + results = fmgr_get_task_status(fmgr, paramgram) + if results[0] != 0: + module.fail_json(**results[1]) + if results[0] == 0: + module.exit_json(**results[1]) + except Exception as err: + raise FMGBaseException(err) + + try: + # IF OBJECT IS CUSTOM + if paramgram["object"] == "custom": + results = fmgr_get_custom(fmgr, paramgram) + if results[0] != 0: + module.fail_json(msg="QUERY FAILED -- Please check syntax check JSON guide if needed.") + if results[0] == 0: + results_len = len(results[1]) + if results_len > 0: + results_combine = dict() + if isinstance(results[1], dict): + results_combine["results"] = results[1] + if isinstance(results[1], list): + results_combine["results"] = results[1][0:results_len] + module.exit_json(msg="Custom Query Success", **results_combine) + else: + module.exit_json(msg="NO RESULTS") + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_script.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_script.py new file mode 100644 index 00000000..d84606cc --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_script.py @@ -0,0 +1,262 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_script +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: Andrew Welsh (@Ghilli3) +short_description: Add/Edit/Delete and execute scripts +description: Create/edit/delete scripts and execute the scripts on the FortiManager using jsonrpc API + +options: + adom: + description: + - The administrative domain (admon) the configuration belongs to + required: true + + vdom: + description: + - The virtual domain (vdom) the configuration belongs to + + mode: + description: + - The desired mode of the specified object. Execute will run the script. + required: false + default: "add" + choices: ["add", "delete", "execute", "set"] + + script_name: + description: + - The name of the script. + required: True + + script_type: + description: + - The type of script (CLI or TCL). + required: false + + script_target: + description: + - The target of the script to be run. + required: false + + script_description: + description: + - The description of the script. + required: false + + script_content: + description: + - The script content that will be executed. + required: false + + script_scope: + description: + - (datasource) The devices that the script will run on, can have both device member and device group member. + required: false + + script_package: + description: + - (datasource) Policy package object to run the script against + required: false +''' + +EXAMPLES = ''' +- name: CREATE SCRIPT + community.fortios.fmgr_script: + adom: "root" + script_name: "TestScript" + script_type: "cli" + script_target: "remote_device" + script_description: "Create by Ansible" + script_content: "get system status" + +- name: EXECUTE SCRIPT + community.fortios.fmgr_script: + adom: "root" + script_name: "TestScript" + mode: "execute" + script_scope: "FGT1,FGT2" + +- name: DELETE SCRIPT + community.fortios.fmgr_script: + adom: "root" + script_name: "TestScript" + mode: "delete" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG + + +def set_script(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + datagram = { + 'content': paramgram["script_content"], + 'desc': paramgram["script_description"], + 'name': paramgram["script_name"], + 'target': paramgram["script_target"], + 'type': paramgram["script_type"], + } + + url = '/dvmdb/adom/{adom}/script/'.format(adom=paramgram["adom"]) + response = fmgr.process_request(url, datagram, FMGRMethods.SET) + return response + + +def delete_script(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + datagram = { + 'name': paramgram["script_name"], + } + + url = '/dvmdb/adom/{adom}/script/{script_name}'.format(adom=paramgram["adom"], script_name=paramgram["script_name"]) + response = fmgr.process_request(url, datagram, FMGRMethods.DELETE) + return response + + +def execute_script(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + scope_list = list() + scope = paramgram["script_scope"].replace(' ', '') + scope = scope.split(',') + for dev_name in scope: + scope_list.append({'name': dev_name, 'vdom': paramgram["vdom"]}) + + datagram = { + 'adom': paramgram["adom"], + 'script': paramgram["script_name"], + 'package': paramgram["script_package"], + 'scope': scope_list, + } + + url = '/dvmdb/adom/{adom}/script/execute'.format(adom=paramgram["adom"]) + response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) + return response + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + vdom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "execute", "set", "delete"], type="str", default="add"), + script_name=dict(required=True, type="str"), + script_type=dict(required=False, type="str"), + script_target=dict(required=False, type="str"), + script_description=dict(required=False, type="str"), + script_content=dict(required=False, type="str"), + script_scope=dict(required=False, type="str"), + script_package=dict(required=False, type="str"), + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + paramgram = { + "script_name": module.params["script_name"], + "script_type": module.params["script_type"], + "script_target": module.params["script_target"], + "script_description": module.params["script_description"], + "script_content": module.params["script_content"], + "script_scope": module.params["script_scope"], + "script_package": module.params["script_package"], + "adom": module.params["adom"], + "vdom": module.params["vdom"], + "mode": module.params["mode"], + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + + try: + if paramgram["mode"] in ['add', 'set']: + results = set_script(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, msg="Operation Finished", + ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params)) + except Exception as err: + raise FMGBaseException(err) + + try: + if paramgram["mode"] == "execute": + results = execute_script(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, msg="Operation Finished", + ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params)) + except Exception as err: + raise FMGBaseException(err) + + try: + if paramgram["mode"] == "delete": + results = delete_script(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, msg="Operation Finished", + ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_appctrl.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_appctrl.py new file mode 100644 index 00000000..aabd2985 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_appctrl.py @@ -0,0 +1,516 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_appctrl +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage application control security profiles +description: + - Manage application control security profiles within FortiManager + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + unknown_application_log: + description: + - Enable/disable logging for unknown applications. + - choice | disable | Disable logging for unknown applications. + - choice | enable | Enable logging for unknown applications. + required: false + choices: ["disable", "enable"] + + unknown_application_action: + description: + - Pass or block traffic from unknown applications. + - choice | pass | Pass or allow unknown applications. + - choice | block | Drop or block unknown applications. + required: false + choices: ["pass", "block"] + + replacemsg_group: + description: + - Replacement message group. + required: false + + p2p_black_list: + description: + - NO DESCRIPTION PARSED ENTER MANUALLY + - FLAG Based Options. Specify multiple in list form. + - flag | skype | Skype. + - flag | edonkey | Edonkey. + - flag | bittorrent | Bit torrent. + required: false + choices: ["skype", "edonkey", "bittorrent"] + + other_application_log: + description: + - Enable/disable logging for other applications. + - choice | disable | Disable logging for other applications. + - choice | enable | Enable logging for other applications. + required: false + choices: ["disable", "enable"] + + other_application_action: + description: + - Action for other applications. + - choice | pass | Allow sessions matching an application in this application list. + - choice | block | Block sessions matching an application in this application list. + required: false + choices: ["pass", "block"] + + options: + description: + - NO DESCRIPTION PARSED ENTER MANUALLY + - FLAG Based Options. Specify multiple in list form. + - flag | allow-dns | Allow DNS. + - flag | allow-icmp | Allow ICMP. + - flag | allow-http | Allow generic HTTP web browsing. + - flag | allow-ssl | Allow generic SSL communication. + - flag | allow-quic | Allow QUIC. + required: false + choices: ["allow-dns", "allow-icmp", "allow-http", "allow-ssl", "allow-quic"] + + name: + description: + - List name. + required: false + + extended_log: + description: + - Enable/disable extended logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + deep_app_inspection: + description: + - Enable/disable deep application inspection. + - choice | disable | Disable deep application inspection. + - choice | enable | Enable deep application inspection. + required: false + choices: ["disable", "enable"] + + comment: + description: + - comments + required: false + + app_replacemsg: + description: + - Enable/disable replacement messages for blocked applications. + - choice | disable | Disable replacement messages for blocked applications. + - choice | enable | Enable replacement messages for blocked applications. + required: false + choices: ["disable", "enable"] + + entries: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, OMIT THE USE OF THIS PARAMETER + - AND USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + entries_action: + description: + - Pass or block traffic, or reset connection for traffic from this application. + - choice | pass | Pass or allow matching traffic. + - choice | block | Block or drop matching traffic. + - choice | reset | Reset sessions for matching traffic. + required: false + choices: ["pass", "block", "reset"] + + entries_application: + description: + - ID of allowed applications. + required: false + + entries_behavior: + description: + - Application behavior filter. + required: false + + entries_category: + description: + - Category ID list. + required: false + + entries_log: + description: + - Enable/disable logging for this application list. + - choice | disable | Disable logging. + - choice | enable | Enable logging. + required: false + choices: ["disable", "enable"] + + entries_log_packet: + description: + - Enable/disable packet logging. + - choice | disable | Disable packet logging. + - choice | enable | Enable packet logging. + required: false + choices: ["disable", "enable"] + + entries_per_ip_shaper: + description: + - Per-IP traffic shaper. + required: false + + entries_popularity: + description: + - Application popularity filter (1 - 5, from least to most popular). + - FLAG Based Options. Specify multiple in list form. + - flag | 1 | Popularity level 1. + - flag | 2 | Popularity level 2. + - flag | 3 | Popularity level 3. + - flag | 4 | Popularity level 4. + - flag | 5 | Popularity level 5. + required: false + choices: ["1", "2", "3", "4", "5"] + + entries_protocols: + description: + - Application protocol filter. + required: false + + entries_quarantine: + description: + - Quarantine method. + - choice | none | Quarantine is disabled. + - choice | attacker | Block all traffic sent from attacker's IP address. + - The attacker's IP address is also added to the banned user list. The target's address is not affected. + required: false + choices: ["none", "attacker"] + + entries_quarantine_expiry: + description: + - Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m, default = 5m). + - Requires quarantine set to attacker. + required: false + + entries_quarantine_log: + description: + - Enable/disable quarantine logging. + - choice | disable | Disable quarantine logging. + - choice | enable | Enable quarantine logging. + required: false + choices: ["disable", "enable"] + + entries_rate_count: + description: + - Count of the rate. + required: false + + entries_rate_duration: + description: + - Duration (sec) of the rate. + required: false + + entries_rate_mode: + description: + - Rate limit mode. + - choice | periodical | Allow configured number of packets every rate-duration. + - choice | continuous | Block packets once the rate is reached. + required: false + choices: ["periodical", "continuous"] + + entries_rate_track: + description: + - Track the packet protocol field. + - choice | none | + - choice | src-ip | Source IP. + - choice | dest-ip | Destination IP. + - choice | dhcp-client-mac | DHCP client. + - choice | dns-domain | DNS domain. + required: false + choices: ["none", "src-ip", "dest-ip", "dhcp-client-mac", "dns-domain"] + + entries_risk: + description: + - Risk, or impact, of allowing traffic from this application to occur 1 - 5; + - (Low, Elevated, Medium, High, and Critical). + required: false + + entries_session_ttl: + description: + - Session TTL (0 = default). + required: false + + entries_shaper: + description: + - Traffic shaper. + required: false + + entries_shaper_reverse: + description: + - Reverse traffic shaper. + required: false + + entries_sub_category: + description: + - Application Sub-category ID list. + required: false + + entries_technology: + description: + - Application technology filter. + required: false + + entries_vendor: + description: + - Application vendor filter. + required: false + + entries_parameters_value: + description: + - Parameter value. + required: false + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_appctrl: + name: "Ansible_Application_Control_Profile" + comment: "Created by Ansible Module TEST" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_appctrl: + name: "Ansible_Application_Control_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" + entries: [{ + action: "block", + log: "enable", + log-packet: "enable", + protocols: ["1"], + quarantine: "attacker", + quarantine-log: "enable", + }, + {action: "pass", + category: ["2","3","4"]}, + ] +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + +############### +# START METHODS +############### + + +def fmgr_application_list_modify(fmgr, paramgram): + """ + fmgr_application_list -- Modifies Application Control Profiles on FortiManager + + :param fmgr: The fmgr object instance from fmgr_utils.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + + :return: The response from the FortiManager + :rtype: dict + """ + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if paramgram["mode"] in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/application/list'.format(adom=paramgram["adom"]) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif paramgram["mode"] == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/application/list/{name}'.format(adom=paramgram["adom"], + name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + unknown_application_log=dict(required=False, type="str", choices=["disable", "enable"]), + unknown_application_action=dict(required=False, type="str", choices=["pass", "block"]), + replacemsg_group=dict(required=False, type="str"), + p2p_black_list=dict(required=False, type="str", choices=["skype", "edonkey", "bittorrent"]), + other_application_log=dict(required=False, type="str", choices=["disable", "enable"]), + other_application_action=dict(required=False, type="str", choices=["pass", "block"]), + options=dict(required=False, type="str", + choices=["allow-dns", "allow-icmp", "allow-http", "allow-ssl", "allow-quic"]), + name=dict(required=False, type="str"), + extended_log=dict(required=False, type="str", choices=["disable", "enable"]), + deep_app_inspection=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + app_replacemsg=dict(required=False, type="str", choices=["disable", "enable"]), + entries=dict(required=False, type="list"), + entries_action=dict(required=False, type="str", choices=["pass", "block", "reset"]), + entries_application=dict(required=False, type="str"), + entries_behavior=dict(required=False, type="str"), + entries_category=dict(required=False, type="str"), + entries_log=dict(required=False, type="str", choices=["disable", "enable"]), + entries_log_packet=dict(required=False, type="str", choices=["disable", "enable"]), + entries_per_ip_shaper=dict(required=False, type="str"), + entries_popularity=dict(required=False, type="str", choices=["1", "2", "3", "4", "5"]), + entries_protocols=dict(required=False, type="str"), + entries_quarantine=dict(required=False, type="str", choices=["none", "attacker"]), + entries_quarantine_expiry=dict(required=False, type="str"), + entries_quarantine_log=dict(required=False, type="str", choices=["disable", "enable"]), + entries_rate_count=dict(required=False, type="int"), + entries_rate_duration=dict(required=False, type="int"), + entries_rate_mode=dict(required=False, type="str", choices=["periodical", "continuous"]), + entries_rate_track=dict(required=False, type="str", + choices=["none", "src-ip", "dest-ip", "dhcp-client-mac", "dns-domain"]), + entries_risk=dict(required=False, type="str"), + entries_session_ttl=dict(required=False, type="int"), + entries_shaper=dict(required=False, type="str"), + entries_shaper_reverse=dict(required=False, type="str"), + entries_sub_category=dict(required=False, type="str"), + entries_technology=dict(required=False, type="str"), + entries_vendor=dict(required=False, type="str"), + + entries_parameters_value=dict(required=False, type="str"), + + ) + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "unknown-application-log": module.params["unknown_application_log"], + "unknown-application-action": module.params["unknown_application_action"], + "replacemsg-group": module.params["replacemsg_group"], + "p2p-black-list": module.params["p2p_black_list"], + "other-application-log": module.params["other_application_log"], + "other-application-action": module.params["other_application_action"], + "options": module.params["options"], + "name": module.params["name"], + "extended-log": module.params["extended_log"], + "deep-app-inspection": module.params["deep_app_inspection"], + "comment": module.params["comment"], + "app-replacemsg": module.params["app_replacemsg"], + "entries": { + "action": module.params["entries_action"], + "application": module.params["entries_application"], + "behavior": module.params["entries_behavior"], + "category": module.params["entries_category"], + "log": module.params["entries_log"], + "log-packet": module.params["entries_log_packet"], + "per-ip-shaper": module.params["entries_per_ip_shaper"], + "popularity": module.params["entries_popularity"], + "protocols": module.params["entries_protocols"], + "quarantine": module.params["entries_quarantine"], + "quarantine-expiry": module.params["entries_quarantine_expiry"], + "quarantine-log": module.params["entries_quarantine_log"], + "rate-count": module.params["entries_rate_count"], + "rate-duration": module.params["entries_rate_duration"], + "rate-mode": module.params["entries_rate_mode"], + "rate-track": module.params["entries_rate_track"], + "risk": module.params["entries_risk"], + "session-ttl": module.params["entries_session_ttl"], + "shaper": module.params["entries_shaper"], + "shaper-reverse": module.params["entries_shaper_reverse"], + "sub-category": module.params["entries_sub_category"], + "technology": module.params["entries_technology"], + "vendor": module.params["entries_vendor"], + "parameters": { + "value": module.params["entries_parameters_value"], + } + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['entries'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + try: + results = fmgr_application_list_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_av.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_av.py new file mode 100644 index 00000000..88375cf1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_av.py @@ -0,0 +1,1386 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_av +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage security profile +description: + - Manage security profile groups for FortiManager objects + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + scan_mode: + description: + - Choose between full scan mode and quick scan mode. + required: false + choices: + - quick + - full + + replacemsg_group: + description: + - Replacement message group customized for this profile. + required: false + + name: + description: + - Profile name. + required: false + + mobile_malware_db: + description: + - Enable/disable using the mobile malware signature database. + required: false + choices: + - disable + - enable + + inspection_mode: + description: + - Inspection mode. + required: false + choices: + - proxy + - flow-based + + ftgd_analytics: + description: + - Settings to control which files are uploaded to FortiSandbox. + required: false + choices: + - disable + - suspicious + - everything + + extended_log: + description: + - Enable/disable extended logging for antivirus. + required: false + choices: + - disable + - enable + + comment: + description: + - Comment. + required: false + + av_virus_log: + description: + - Enable/disable AntiVirus logging. + required: false + choices: + - disable + - enable + + av_block_log: + description: + - Enable/disable logging for AntiVirus file blocking. + required: false + choices: + - disable + - enable + + analytics_wl_filetype: + description: + - Do not submit files matching this DLP file-pattern to FortiSandbox. + required: false + + analytics_max_upload: + description: + - Maximum size of files that can be uploaded to FortiSandbox (1 - 395 MBytes, default = 10). + required: false + + analytics_db: + description: + - Enable/disable using the FortiSandbox signature database to supplement the AV signature databases. + required: false + choices: + - disable + - enable + + analytics_bl_filetype: + description: + - Only submit files matching this DLP file-pattern to FortiSandbox. + required: false + + content_disarm: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + content_disarm_cover_page: + description: + - Enable/disable inserting a cover page into the disarmed document. + required: false + choices: + - disable + - enable + + content_disarm_detect_only: + description: + - Enable/disable only detect disarmable files, do not alter content. + required: false + choices: + - disable + - enable + + content_disarm_office_embed: + description: + - Enable/disable stripping of embedded objects in Microsoft Office documents. + required: false + choices: + - disable + - enable + + content_disarm_office_hylink: + description: + - Enable/disable stripping of hyperlinks in Microsoft Office documents. + required: false + choices: + - disable + - enable + + content_disarm_office_linked: + description: + - Enable/disable stripping of linked objects in Microsoft Office documents. + required: false + choices: + - disable + - enable + + content_disarm_office_macro: + description: + - Enable/disable stripping of macros in Microsoft Office documents. + required: false + choices: + - disable + - enable + + content_disarm_original_file_destination: + description: + - Destination to send original file if active content is removed. + required: false + choices: + - fortisandbox + - quarantine + - discard + + content_disarm_pdf_act_form: + description: + - Enable/disable stripping of actions that submit data to other targets in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_act_gotor: + description: + - Enable/disable stripping of links to other PDFs in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_act_java: + description: + - Enable/disable stripping of actions that execute JavaScript code in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_act_launch: + description: + - Enable/disable stripping of links to external applications in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_act_movie: + description: + - Enable/disable stripping of embedded movies in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_act_sound: + description: + - Enable/disable stripping of embedded sound files in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_embedfile: + description: + - Enable/disable stripping of embedded files in PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_hyperlink: + description: + - Enable/disable stripping of hyperlinks from PDF documents. + required: false + choices: + - disable + - enable + + content_disarm_pdf_javacode: + description: + - Enable/disable stripping of JavaScript code in PDF documents. + required: false + choices: + - disable + - enable + + ftp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ftp_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + ftp_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + ftp_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + ftp_options: + description: + - Enable/disable FTP AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + ftp_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + http: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + http_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + http_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + http_content_disarm: + description: + - Enable Content Disarm and Reconstruction for this protocol. + required: false + choices: + - disable + - enable + + http_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + http_options: + description: + - Enable/disable HTTP AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + http_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + imap: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + imap_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + imap_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + imap_content_disarm: + description: + - Enable Content Disarm and Reconstruction for this protocol. + required: false + choices: + - disable + - enable + + imap_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + imap_executables: + description: + - Treat Windows executable files as viruses for the purpose of blocking or monitoring. + required: false + choices: + - default + - virus + + imap_options: + description: + - Enable/disable IMAP AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + imap_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + mapi: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + mapi_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + mapi_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + mapi_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + mapi_executables: + description: + - Treat Windows executable files as viruses for the purpose of blocking or monitoring. + required: false + choices: + - default + - virus + + mapi_options: + description: + - Enable/disable MAPI AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + mapi_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + nac_quar: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + nac_quar_expiry: + description: + - Duration of quarantine. + required: false + + nac_quar_infected: + description: + - Enable/Disable quarantining infected hosts to the banned user list. + required: false + choices: + - none + - quar-src-ip + + nac_quar_log: + description: + - Enable/disable AntiVirus quarantine logging. + required: false + choices: + - disable + - enable + + nntp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + nntp_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + nntp_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + nntp_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + nntp_options: + description: + - Enable/disable NNTP AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + nntp_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + pop3: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + pop3_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + pop3_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + pop3_content_disarm: + description: + - Enable Content Disarm and Reconstruction for this protocol. + required: false + choices: + - disable + - enable + + pop3_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + pop3_executables: + description: + - Treat Windows executable files as viruses for the purpose of blocking or monitoring. + required: false + choices: + - default + - virus + + pop3_options: + description: + - Enable/disable POP3 AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + pop3_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + smb: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + smb_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + smb_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + smb_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + smb_options: + description: + - Enable/disable SMB AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + smb_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive + + smtp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + smtp_archive_block: + description: + - Select the archive types to block. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + smtp_archive_log: + description: + - Select the archive types to log. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - encrypted + - corrupted + - multipart + - nested + - mailbomb + - unhandled + - partiallycorrupted + - fileslimit + - timeout + + smtp_content_disarm: + description: + - Enable Content Disarm and Reconstruction for this protocol. + required: false + choices: + - disable + - enable + + smtp_emulator: + description: + - Enable/disable the virus emulator. + required: false + choices: + - disable + - enable + + smtp_executables: + description: + - Treat Windows executable files as viruses for the purpose of blocking or monitoring. + required: false + choices: + - default + - virus + + smtp_options: + description: + - Enable/disable SMTP AntiVirus scanning, monitoring, and quarantine. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - scan + - quarantine + - avmonitor + + smtp_outbreak_prevention: + description: + - Enable FortiGuard Virus Outbreak Prevention service. + required: false + choices: + - disabled + - files + - full-archive +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_av: + name: "Ansible_AV_Profile" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_av: + name: "Ansible_AV_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" + inspection_mode: "proxy" + ftgd_analytics: "everything" + av_block_log: "enable" + av_virus_log: "enable" + scan_mode: "full" + mobile_malware_db: "enable" + ftp_archive_block: "encrypted" + ftp_outbreak_prevention: "files" + ftp_archive_log: "timeout" + ftp_emulator: "disable" + ftp_options: "scan" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + +############### +# START METHODS +############### + + +def fmgr_antivirus_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/antivirus/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + else: + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/antivirus/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + return response + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(required=False, type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + scan_mode=dict(required=False, type="str", choices=["quick", "full"]), + replacemsg_group=dict(required=False, type="dict"), + name=dict(required=False, type="str"), + mobile_malware_db=dict(required=False, type="str", choices=["disable", "enable"]), + inspection_mode=dict(required=False, type="str", choices=["proxy", "flow-based"]), + ftgd_analytics=dict(required=False, type="str", choices=["disable", "suspicious", "everything"]), + extended_log=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + av_virus_log=dict(required=False, type="str", choices=["disable", "enable"]), + av_block_log=dict(required=False, type="str", choices=["disable", "enable"]), + analytics_wl_filetype=dict(required=False, type="dict"), + analytics_max_upload=dict(required=False, type="int"), + analytics_db=dict(required=False, type="str", choices=["disable", "enable"]), + analytics_bl_filetype=dict(required=False, type="dict"), + content_disarm=dict(required=False, type="list"), + content_disarm_cover_page=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_detect_only=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_office_embed=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_office_hylink=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_office_linked=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_office_macro=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_original_file_destination=dict(required=False, type="str", choices=["fortisandbox", + "quarantine", + "discard"]), + content_disarm_pdf_act_form=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_act_gotor=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_act_java=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_act_launch=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_act_movie=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_act_sound=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_embedfile=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_hyperlink=dict(required=False, type="str", choices=["disable", "enable"]), + content_disarm_pdf_javacode=dict(required=False, type="str", choices=["disable", "enable"]), + ftp=dict(required=False, type="list"), + ftp_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + ftp_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + ftp_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + ftp_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + ftp_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + http=dict(required=False, type="list"), + http_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + http_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + http_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]), + http_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + http_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + http_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + imap=dict(required=False, type="list"), + imap_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + imap_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + imap_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]), + imap_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + imap_executables=dict(required=False, type="str", choices=["default", "virus"]), + imap_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + imap_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + mapi=dict(required=False, type="list"), + mapi_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + mapi_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + mapi_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + mapi_executables=dict(required=False, type="str", choices=["default", "virus"]), + mapi_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + mapi_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + nac_quar=dict(required=False, type="list"), + nac_quar_expiry=dict(required=False, type="str"), + nac_quar_infected=dict(required=False, type="str", choices=["none", "quar-src-ip"]), + nac_quar_log=dict(required=False, type="str", choices=["disable", "enable"]), + nntp=dict(required=False, type="list"), + nntp_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + nntp_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + nntp_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + nntp_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + nntp_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + pop3=dict(required=False, type="list"), + pop3_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + pop3_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + pop3_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]), + pop3_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + pop3_executables=dict(required=False, type="str", choices=["default", "virus"]), + pop3_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + pop3_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + smb=dict(required=False, type="list"), + smb_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + smb_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + smb_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + smb_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + smb_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + smtp=dict(required=False, type="list"), + smtp_archive_block=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + smtp_archive_log=dict(required=False, type="str", choices=["encrypted", + "corrupted", + "multipart", + "nested", + "mailbomb", + "unhandled", + "partiallycorrupted", + "fileslimit", + "timeout"]), + smtp_content_disarm=dict(required=False, type="str", choices=["disable", "enable"]), + smtp_emulator=dict(required=False, type="str", choices=["disable", "enable"]), + smtp_executables=dict(required=False, type="str", choices=["default", "virus"]), + smtp_options=dict(required=False, type="str", choices=["scan", "quarantine", "avmonitor"]), + smtp_outbreak_prevention=dict(required=False, type="str", choices=["disabled", "files", "full-archive"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "scan-mode": module.params["scan_mode"], + "replacemsg-group": module.params["replacemsg_group"], + "name": module.params["name"], + "mobile-malware-db": module.params["mobile_malware_db"], + "inspection-mode": module.params["inspection_mode"], + "ftgd-analytics": module.params["ftgd_analytics"], + "extended-log": module.params["extended_log"], + "comment": module.params["comment"], + "av-virus-log": module.params["av_virus_log"], + "av-block-log": module.params["av_block_log"], + "analytics-wl-filetype": module.params["analytics_wl_filetype"], + "analytics-max-upload": module.params["analytics_max_upload"], + "analytics-db": module.params["analytics_db"], + "analytics-bl-filetype": module.params["analytics_bl_filetype"], + "content-disarm": { + "cover-page": module.params["content_disarm_cover_page"], + "detect-only": module.params["content_disarm_detect_only"], + "office-embed": module.params["content_disarm_office_embed"], + "office-hylink": module.params["content_disarm_office_hylink"], + "office-linked": module.params["content_disarm_office_linked"], + "office-macro": module.params["content_disarm_office_macro"], + "original-file-destination": module.params["content_disarm_original_file_destination"], + "pdf-act-form": module.params["content_disarm_pdf_act_form"], + "pdf-act-gotor": module.params["content_disarm_pdf_act_gotor"], + "pdf-act-java": module.params["content_disarm_pdf_act_java"], + "pdf-act-launch": module.params["content_disarm_pdf_act_launch"], + "pdf-act-movie": module.params["content_disarm_pdf_act_movie"], + "pdf-act-sound": module.params["content_disarm_pdf_act_sound"], + "pdf-embedfile": module.params["content_disarm_pdf_embedfile"], + "pdf-hyperlink": module.params["content_disarm_pdf_hyperlink"], + "pdf-javacode": module.params["content_disarm_pdf_javacode"], + }, + "ftp": { + "archive-block": module.params["ftp_archive_block"], + "archive-log": module.params["ftp_archive_log"], + "emulator": module.params["ftp_emulator"], + "options": module.params["ftp_options"], + "outbreak-prevention": module.params["ftp_outbreak_prevention"], + }, + "http": { + "archive-block": module.params["http_archive_block"], + "archive-log": module.params["http_archive_log"], + "content-disarm": module.params["http_content_disarm"], + "emulator": module.params["http_emulator"], + "options": module.params["http_options"], + "outbreak-prevention": module.params["http_outbreak_prevention"], + }, + "imap": { + "archive-block": module.params["imap_archive_block"], + "archive-log": module.params["imap_archive_log"], + "content-disarm": module.params["imap_content_disarm"], + "emulator": module.params["imap_emulator"], + "executables": module.params["imap_executables"], + "options": module.params["imap_options"], + "outbreak-prevention": module.params["imap_outbreak_prevention"], + }, + "mapi": { + "archive-block": module.params["mapi_archive_block"], + "archive-log": module.params["mapi_archive_log"], + "emulator": module.params["mapi_emulator"], + "executables": module.params["mapi_executables"], + "options": module.params["mapi_options"], + "outbreak-prevention": module.params["mapi_outbreak_prevention"], + }, + "nac-quar": { + "expiry": module.params["nac_quar_expiry"], + "infected": module.params["nac_quar_infected"], + "log": module.params["nac_quar_log"], + }, + "nntp": { + "archive-block": module.params["nntp_archive_block"], + "archive-log": module.params["nntp_archive_log"], + "emulator": module.params["nntp_emulator"], + "options": module.params["nntp_options"], + "outbreak-prevention": module.params["nntp_outbreak_prevention"], + }, + "pop3": { + "archive-block": module.params["pop3_archive_block"], + "archive-log": module.params["pop3_archive_log"], + "content-disarm": module.params["pop3_content_disarm"], + "emulator": module.params["pop3_emulator"], + "executables": module.params["pop3_executables"], + "options": module.params["pop3_options"], + "outbreak-prevention": module.params["pop3_outbreak_prevention"], + }, + "smb": { + "archive-block": module.params["smb_archive_block"], + "archive-log": module.params["smb_archive_log"], + "emulator": module.params["smb_emulator"], + "options": module.params["smb_options"], + "outbreak-prevention": module.params["smb_outbreak_prevention"], + }, + "smtp": { + "archive-block": module.params["smtp_archive_block"], + "archive-log": module.params["smtp_archive_log"], + "content-disarm": module.params["smtp_content_disarm"], + "emulator": module.params["smtp_emulator"], + "executables": module.params["smtp_executables"], + "options": module.params["smtp_options"], + "outbreak-prevention": module.params["smtp_outbreak_prevention"], + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ["content-disarm", "ftp", "http", "imap", "mapi", "nac-quar", "nntp", "pop3", "smb", "smtp"] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + module.paramgram = paramgram + + results = DEFAULT_RESULT_OBJ + + try: + results = fmgr_antivirus_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_dns.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_dns.py new file mode 100644 index 00000000..e6157ff4 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_dns.py @@ -0,0 +1,339 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_dns +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage DNS security profiles in FortiManager +description: + - Manage DNS security profiles in FortiManager + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values. + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + youtube_restrict: + type: str + description: + - Set safe search for YouTube restriction level. + - choice | strict | Enable strict safe seach for YouTube. + - choice | moderate | Enable moderate safe search for YouTube. + required: false + choices: ["strict", "moderate"] + + sdns_ftgd_err_log: + type: str + description: + - Enable/disable FortiGuard SDNS rating error logging. + - choice | disable | Disable FortiGuard SDNS rating error logging. + - choice | enable | Enable FortiGuard SDNS rating error logging. + required: false + choices: ["disable", "enable"] + + sdns_domain_log: + type: str + description: + - Enable/disable domain filtering and botnet domain logging. + - choice | disable | Disable domain filtering and botnet domain logging. + - choice | enable | Enable domain filtering and botnet domain logging. + required: false + choices: ["disable", "enable"] + + safe_search: + type: str + description: + - Enable/disable Google, Bing, and YouTube safe search. + - choice | disable | Disable Google, Bing, and YouTube safe search. + - choice | enable | Enable Google, Bing, and YouTube safe search. + required: false + choices: ["disable", "enable"] + + redirect_portal: + type: str + description: + - IP address of the SDNS redirect portal. + required: false + + name: + type: str + description: + - Profile name. + required: false + + log_all_domain: + type: str + description: + - Enable/disable logging of all domains visited (detailed DNS logging). + - choice | disable | Disable logging of all domains visited. + - choice | enable | Enable logging of all domains visited. + required: false + choices: ["disable", "enable"] + + external_ip_blocklist: + type: str + description: + - One or more external IP block lists. + required: false + + comment: + type: str + description: + - Comment for the security profile to show in the FortiManager GUI. + required: false + + block_botnet: + type: str + description: + - Enable/disable blocking botnet C&C; DNS lookups. + - choice | disable | Disable blocking botnet C&C; DNS lookups. + - choice | enable | Enable blocking botnet C&C; DNS lookups. + required: false + choices: ["disable", "enable"] + + block_action: + type: str + description: + - Action to take for blocked domains. + - choice | block | Return NXDOMAIN for blocked domains. + - choice | redirect | Redirect blocked domains to SDNS portal. + required: false + choices: ["block", "redirect"] + + domain_filter_domain_filter_table: + type: str + description: + - DNS domain filter table ID. + required: false + + ftgd_dns_options: + type: str + description: + - FortiGuard DNS filter options. + - FLAG Based Options. Specify multiple in list form. + - flag | error-allow | Allow all domains when FortiGuard DNS servers fail. + - flag | ftgd-disable | Disable FortiGuard DNS domain rating. + required: false + choices: ["error-allow", "ftgd-disable"] + + ftgd_dns_filters_action: + type: str + description: + - Action to take for DNS requests matching the category. + - choice | monitor | Allow DNS requests matching the category and log the result. + - choice | block | Block DNS requests matching the category. + required: false + choices: ["monitor", "block"] + + ftgd_dns_filters_category: + type: str + description: + - Category number. + required: false + + ftgd_dns_filters_log: + type: str + description: + - Enable/disable DNS filter logging for this DNS profile. + - choice | disable | Disable DNS filter logging. + - choice | enable | Enable DNS filter logging. + required: false + choices: ["disable", "enable"] + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_dns: + name: "Ansible_DNS_Profile" + comment: "Created by Ansible Module TEST" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_dns: + name: "Ansible_DNS_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" + block_action: "block" + + +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_dnsfilter_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + url = "" + datagram = {} + + response = DEFAULT_RESULT_OBJ + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/dnsfilter/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/dnsfilter/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + youtube_restrict=dict(required=False, type="str", choices=["strict", "moderate"]), + sdns_ftgd_err_log=dict(required=False, type="str", choices=["disable", "enable"]), + sdns_domain_log=dict(required=False, type="str", choices=["disable", "enable"]), + safe_search=dict(required=False, type="str", choices=["disable", "enable"]), + redirect_portal=dict(required=False, type="str"), + name=dict(required=False, type="str"), + log_all_domain=dict(required=False, type="str", choices=["disable", "enable"]), + external_ip_blocklist=dict(required=False, type="str"), + comment=dict(required=False, type="str"), + block_botnet=dict(required=False, type="str", choices=["disable", "enable"]), + block_action=dict(required=False, type="str", choices=["block", "redirect"]), + + domain_filter_domain_filter_table=dict(required=False, type="str"), + + ftgd_dns_options=dict(required=False, type="str", choices=["error-allow", "ftgd-disable"]), + + ftgd_dns_filters_action=dict(required=False, type="str", choices=["monitor", "block"]), + ftgd_dns_filters_category=dict(required=False, type="str"), + ftgd_dns_filters_log=dict(required=False, type="str", choices=["disable", "enable"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "youtube-restrict": module.params["youtube_restrict"], + "sdns-ftgd-err-log": module.params["sdns_ftgd_err_log"], + "sdns-domain-log": module.params["sdns_domain_log"], + "safe-search": module.params["safe_search"], + "redirect-portal": module.params["redirect_portal"], + "name": module.params["name"], + "log-all-domain": module.params["log_all_domain"], + "external-ip-blocklist": module.params["external_ip_blocklist"], + "comment": module.params["comment"], + "block-botnet": module.params["block_botnet"], + "block-action": module.params["block_action"], + "domain-filter": { + "domain-filter-table": module.params["domain_filter_domain_filter_table"], + }, + "ftgd-dns": { + "options": module.params["ftgd_dns_options"], + "filters": { + "action": module.params["ftgd_dns_filters_action"], + "category": module.params["ftgd_dns_filters_category"], + "log": module.params["ftgd_dns_filters_log"], + } + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + + try: + results = fmgr_dnsfilter_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_ips.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_ips.py new file mode 100644 index 00000000..4b5f8996 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_ips.py @@ -0,0 +1,664 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_ips +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Managing IPS security profiles in FortiManager +description: + - Managing IPS security profiles in FortiManager + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + replacemsg_group: + description: + - Replacement message group. + required: false + + name: + description: + - Sensor name. + required: false + + extended_log: + description: + - Enable/disable extended logging. + required: false + choices: + - disable + - enable + + comment: + description: + - Comment. + required: false + + block_malicious_url: + description: + - Enable/disable malicious URL blocking. + required: false + choices: + - disable + - enable + + entries: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + entries_action: + description: + - Action taken with traffic in which signatures are detected. + required: false + choices: + - pass + - block + - reset + - default + + entries_application: + description: + - Applications to be protected. set application ? lists available applications. all includes + all applications. other includes all unlisted applications. + required: false + + entries_location: + description: + - Protect client or server traffic. + required: false + + entries_log: + description: + - Enable/disable logging of signatures included in filter. + required: false + choices: + - disable + - enable + + entries_log_attack_context: + description: + - Enable/disable logging of attack context| URL buffer, header buffer, body buffer, packet buffer. + required: false + choices: + - disable + - enable + + entries_log_packet: + description: + - Enable/disable packet logging. Enable to save the packet that triggers the filter. You can + download the packets in pcap format for diagnostic use. + required: false + choices: + - disable + - enable + + entries_os: + description: + - Operating systems to be protected. all includes all operating systems. other includes all + unlisted operating systems. + required: false + + entries_protocol: + description: + - Protocols to be examined. set protocol ? lists available protocols. all includes all protocols. + other includes all unlisted protocols. + required: false + + entries_quarantine: + description: + - Quarantine method. + required: false + choices: + - none + - attacker + + entries_quarantine_expiry: + description: + - Duration of quarantine. + required: false + + entries_quarantine_log: + description: + - Enable/disable quarantine logging. + required: false + choices: + - disable + - enable + + entries_rate_count: + description: + - Count of the rate. + required: false + + entries_rate_duration: + description: + - Duration (sec) of the rate. + required: false + + entries_rate_mode: + description: + - Rate limit mode. + required: false + choices: + - periodical + - continuous + + entries_rate_track: + description: + - Track the packet protocol field. + required: false + choices: + - none + - src-ip + - dest-ip + - dhcp-client-mac + - dns-domain + + entries_rule: + description: + - Identifies the predefined or custom IPS signatures to add to the sensor. + required: false + + entries_severity: + description: + - Relative severity of the signature, from info to critical. Log messages generated by the signature + include the severity. + required: false + + entries_status: + description: + - Status of the signatures included in filter. default enables the filter and only use filters + with default status of enable. Filters with default status of disable will not be used. + required: false + choices: + - disable + - enable + - default + + entries_exempt_ip_dst_ip: + description: + - Destination IP address and netmask. + required: false + + entries_exempt_ip_src_ip: + description: + - Source IP address and netmask. + required: false + + filter: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + filter_action: + description: + - Action of selected rules. + required: false + choices: + - pass + - block + - default + - reset + + filter_application: + description: + - Vulnerable application filter. + required: false + + filter_location: + description: + - Vulnerability location filter. + required: false + + filter_log: + description: + - Enable/disable logging of selected rules. + required: false + choices: + - disable + - enable + + filter_log_packet: + description: + - Enable/disable packet logging of selected rules. + required: false + choices: + - disable + - enable + + filter_name: + description: + - Filter name. + required: false + + filter_os: + description: + - Vulnerable OS filter. + required: false + + filter_protocol: + description: + - Vulnerable protocol filter. + required: false + + filter_quarantine: + description: + - Quarantine IP or interface. + required: false + choices: + - none + - attacker + + filter_quarantine_expiry: + description: + - Duration of quarantine in minute. + required: false + + filter_quarantine_log: + description: + - Enable/disable logging of selected quarantine. + required: false + choices: + - disable + - enable + + filter_severity: + description: + - Vulnerability severity filter. + required: false + + filter_status: + description: + - Selected rules status. + required: false + choices: + - disable + - enable + - default + + override: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + override_action: + description: + - Action of override rule. + required: false + choices: + - pass + - block + - reset + + override_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + override_log_packet: + description: + - Enable/disable packet logging. + required: false + choices: + - disable + - enable + + override_quarantine: + description: + - Quarantine IP or interface. + required: false + choices: + - none + - attacker + + override_quarantine_expiry: + description: + - Duration of quarantine in minute. + required: false + + override_quarantine_log: + description: + - Enable/disable logging of selected quarantine. + required: false + choices: + - disable + - enable + + override_rule_id: + description: + - Override rule ID. + required: false + + override_status: + description: + - Enable/disable status of override rule. + required: false + choices: + - disable + - enable + + override_exempt_ip_dst_ip: + description: + - Destination IP address and netmask. + required: false + + override_exempt_ip_src_ip: + description: + - Source IP address and netmask. + required: false +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_ips: + name: "Ansible_IPS_Profile" + comment: "Created by Ansible Module TEST" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_ips: + name: "Ansible_IPS_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" + block_malicious_url: "enable" + entries: [{severity: "high", action: "block", log-packet: "enable"}, {severity: "medium", action: "pass"}] +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_ips_sensor_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/ips/sensor'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/ips/sensor/{name}'.format( + adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], + type="str", default="add"), + + replacemsg_group=dict(required=False, type="str"), + name=dict(required=False, type="str"), + extended_log=dict(required=False, type="str", + choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + block_malicious_url=dict(required=False, type="str", choices=[ + "disable", "enable"]), + entries=dict(required=False, type="list"), + entries_action=dict(required=False, type="str", choices=[ + "pass", "block", "reset", "default"]), + entries_application=dict(required=False, type="str"), + entries_location=dict(required=False, type="str"), + entries_log=dict(required=False, type="str", + choices=["disable", "enable"]), + entries_log_attack_context=dict( + required=False, type="str", choices=["disable", "enable"]), + entries_log_packet=dict(required=False, type="str", choices=[ + "disable", "enable"]), + entries_os=dict(required=False, type="str"), + entries_protocol=dict(required=False, type="str"), + entries_quarantine=dict(required=False, type="str", choices=[ + "none", "attacker"]), + entries_quarantine_expiry=dict(required=False, type="str"), + entries_quarantine_log=dict( + required=False, type="str", choices=["disable", "enable"]), + entries_rate_count=dict(required=False, type="int"), + entries_rate_duration=dict(required=False, type="int"), + entries_rate_mode=dict(required=False, type="str", choices=[ + "periodical", "continuous"]), + entries_rate_track=dict(required=False, type="str", + choices=["none", "src-ip", "dest-ip", "dhcp-client-mac", "dns-domain"]), + entries_rule=dict(required=False, type="str"), + entries_severity=dict(required=False, type="str"), + entries_status=dict(required=False, type="str", choices=[ + "disable", "enable", "default"]), + + entries_exempt_ip_dst_ip=dict(required=False, type="str"), + entries_exempt_ip_src_ip=dict(required=False, type="str"), + filter=dict(required=False, type="list"), + filter_action=dict(required=False, type="str", choices=[ + "pass", "block", "default", "reset"]), + filter_application=dict(required=False, type="str"), + filter_location=dict(required=False, type="str"), + filter_log=dict(required=False, type="str", + choices=["disable", "enable"]), + filter_log_packet=dict(required=False, type="str", + choices=["disable", "enable"]), + filter_name=dict(required=False, type="str"), + filter_os=dict(required=False, type="str"), + filter_protocol=dict(required=False, type="str"), + filter_quarantine=dict(required=False, type="str", + choices=["none", "attacker"]), + filter_quarantine_expiry=dict(required=False, type="int"), + filter_quarantine_log=dict(required=False, type="str", choices=[ + "disable", "enable"]), + filter_severity=dict(required=False, type="str"), + filter_status=dict(required=False, type="str", choices=[ + "disable", "enable", "default"]), + override=dict(required=False, type="list"), + override_action=dict(required=False, type="str", + choices=["pass", "block", "reset"]), + override_log=dict(required=False, type="str", + choices=["disable", "enable"]), + override_log_packet=dict(required=False, type="str", choices=[ + "disable", "enable"]), + override_quarantine=dict(required=False, type="str", choices=[ + "none", "attacker"]), + override_quarantine_expiry=dict(required=False, type="int"), + override_quarantine_log=dict( + required=False, type="str", choices=["disable", "enable"]), + override_rule_id=dict(required=False, type="str"), + override_status=dict(required=False, type="str", + choices=["disable", "enable"]), + + override_exempt_ip_dst_ip=dict(required=False, type="str"), + override_exempt_ip_src_ip=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "replacemsg-group": module.params["replacemsg_group"], + "name": module.params["name"], + "extended-log": module.params["extended_log"], + "comment": module.params["comment"], + "block-malicious-url": module.params["block_malicious_url"], + "entries": { + "action": module.params["entries_action"], + "application": module.params["entries_application"], + "location": module.params["entries_location"], + "log": module.params["entries_log"], + "log-attack-context": module.params["entries_log_attack_context"], + "log-packet": module.params["entries_log_packet"], + "os": module.params["entries_os"], + "protocol": module.params["entries_protocol"], + "quarantine": module.params["entries_quarantine"], + "quarantine-expiry": module.params["entries_quarantine_expiry"], + "quarantine-log": module.params["entries_quarantine_log"], + "rate-count": module.params["entries_rate_count"], + "rate-duration": module.params["entries_rate_duration"], + "rate-mode": module.params["entries_rate_mode"], + "rate-track": module.params["entries_rate_track"], + "rule": module.params["entries_rule"], + "severity": module.params["entries_severity"], + "status": module.params["entries_status"], + "exempt-ip": { + "dst-ip": module.params["entries_exempt_ip_dst_ip"], + "src-ip": module.params["entries_exempt_ip_src_ip"], + }, + }, + "filter": { + "action": module.params["filter_action"], + "application": module.params["filter_application"], + "location": module.params["filter_location"], + "log": module.params["filter_log"], + "log-packet": module.params["filter_log_packet"], + "name": module.params["filter_name"], + "os": module.params["filter_os"], + "protocol": module.params["filter_protocol"], + "quarantine": module.params["filter_quarantine"], + "quarantine-expiry": module.params["filter_quarantine_expiry"], + "quarantine-log": module.params["filter_quarantine_log"], + "severity": module.params["filter_severity"], + "status": module.params["filter_status"], + }, + "override": { + "action": module.params["override_action"], + "log": module.params["override_log"], + "log-packet": module.params["override_log_packet"], + "quarantine": module.params["override_quarantine"], + "quarantine-expiry": module.params["override_quarantine_expiry"], + "quarantine-log": module.params["override_quarantine_log"], + "rule-id": module.params["override_rule_id"], + "status": module.params["override_status"], + "exempt-ip": { + "dst-ip": module.params["override_exempt_ip_dst_ip"], + "src-ip": module.params["override_exempt_ip_src_ip"], + } + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['entries', 'filter', 'override'] + + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + try: + results = fmgr_ips_sensor_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_profile_group.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_profile_group.py new file mode 100644 index 00000000..4c65abf5 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_profile_group.py @@ -0,0 +1,287 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_profile_group +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage security profiles within FortiManager +description: + - Manage security profile group which allows you to create a group of security profiles and apply that to a policy. + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values. + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + webfilter_profile: + type: str + description: + - Name of an existing Web filter profile. + required: false + + waf_profile: + type: str + description: + - Name of an existing Web application firewall profile. + required: false + + voip_profile: + type: str + description: + - Name of an existing VoIP profile. + required: false + + ssl_ssh_profile: + type: str + description: + - Name of an existing SSL SSH profile. + required: false + + ssh_filter_profile: + type: str + description: + - Name of an existing SSH filter profile. + required: false + + spamfilter_profile: + type: str + description: + - Name of an existing Spam filter profile. + required: false + + profile_protocol_options: + type: str + description: + - Name of an existing Protocol options profile. + required: false + + name: + type: str + description: + - Profile group name. + required: false + + mms_profile: + type: str + description: + - Name of an existing MMS profile. + required: false + + ips_sensor: + type: str + description: + - Name of an existing IPS sensor. + required: false + + icap_profile: + type: str + description: + - Name of an existing ICAP profile. + required: false + + dnsfilter_profile: + type: str + description: + - Name of an existing DNS filter profile. + required: false + + dlp_sensor: + type: str + description: + - Name of an existing DLP sensor. + required: false + + av_profile: + type: str + description: + - Name of an existing Antivirus profile. + required: false + + application_list: + type: str + description: + - Name of an existing Application list. + required: false + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_profile_group: + name: "Ansible_TEST_Profile_Group" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_profile_group: + name: "Ansible_TEST_Profile_Group" + mode: "set" + av_profile: "Ansible_AV_Profile" + profile_protocol_options: "default" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_firewall_profile_group_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + url = "" + datagram = {} + + response = DEFAULT_RESULT_OBJ + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/firewall/profile-group'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/firewall/profile-group/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + webfilter_profile=dict(required=False, type="str"), + waf_profile=dict(required=False, type="str"), + voip_profile=dict(required=False, type="str"), + ssl_ssh_profile=dict(required=False, type="str"), + ssh_filter_profile=dict(required=False, type="str"), + spamfilter_profile=dict(required=False, type="str"), + profile_protocol_options=dict(required=False, type="str"), + name=dict(required=False, type="str"), + mms_profile=dict(required=False, type="str"), + ips_sensor=dict(required=False, type="str"), + icap_profile=dict(required=False, type="str"), + dnsfilter_profile=dict(required=False, type="str"), + dlp_sensor=dict(required=False, type="str"), + av_profile=dict(required=False, type="str"), + application_list=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "webfilter-profile": module.params["webfilter_profile"], + "waf-profile": module.params["waf_profile"], + "voip-profile": module.params["voip_profile"], + "ssl-ssh-profile": module.params["ssl_ssh_profile"], + "ssh-filter-profile": module.params["ssh_filter_profile"], + "spamfilter-profile": module.params["spamfilter_profile"], + "profile-protocol-options": module.params["profile_protocol_options"], + "name": module.params["name"], + "mms-profile": module.params["mms_profile"], + "ips-sensor": module.params["ips_sensor"], + "icap-profile": module.params["icap_profile"], + "dnsfilter-profile": module.params["dnsfilter_profile"], + "dlp-sensor": module.params["dlp_sensor"], + "av-profile": module.params["av_profile"], + "application-list": module.params["application_list"], + + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + results = DEFAULT_RESULT_OBJ + + try: + results = fmgr_firewall_profile_group_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_proxy.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_proxy.py new file mode 100644 index 00000000..1b3ce8d1 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_proxy.py @@ -0,0 +1,332 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_proxy +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage proxy security profiles in FortiManager +description: + - Manage proxy security profiles for FortiGates via FortiManager using the FMG API with playbooks + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + strip_encoding: + description: + - Enable/disable stripping unsupported encoding from the request header. + - choice | disable | Disable stripping of unsupported encoding from the request header. + - choice | enable | Enable stripping of unsupported encoding from the request header. + required: false + choices: ["disable", "enable"] + + name: + description: + - Profile name. + required: false + + log_header_change: + description: + - Enable/disable logging HTTP header changes. + - choice | disable | Disable Enable/disable logging HTTP header changes. + - choice | enable | Enable Enable/disable logging HTTP header changes. + required: false + choices: ["disable", "enable"] + + header_x_forwarded_for: + description: + - Action to take on the HTTP x-forwarded-for header in forwarded requests| forwards (pass), adds, or removes the + - HTTP header. + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + header_x_authenticated_user: + description: + - Action to take on the HTTP x-authenticated-user header in forwarded requests| forwards (pass), adds, or remove + - s the HTTP header. + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + header_x_authenticated_groups: + description: + - Action to take on the HTTP x-authenticated-groups header in forwarded requests| forwards (pass), adds, or remo + - ves the HTTP header. + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + header_via_response: + description: + - Action to take on the HTTP via header in forwarded responses| forwards (pass), adds, or removes the HTTP heade + - r. + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + header_via_request: + description: + - Action to take on the HTTP via header in forwarded requests| forwards (pass), adds, or removes the HTTP header + - . + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + header_front_end_https: + description: + - Action to take on the HTTP front-end-HTTPS header in forwarded requests| forwards (pass), adds, or removes the + - HTTP header. + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + header_client_ip: + description: + - Actions to take on the HTTP client-IP header in forwarded requests| forwards (pass), adds, or removes the HTTP + - header. + - choice | pass | Forward the same HTTP header. + - choice | add | Add the HTTP header. + - choice | remove | Remove the HTTP header. + required: false + choices: ["pass", "add", "remove"] + + headers: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + headers_action: + description: + - Action when HTTP the header forwarded. + - choice | add-to-request | Add the HTTP header to request. + - choice | add-to-response | Add the HTTP header to response. + - choice | remove-from-request | Remove the HTTP header from request. + - choice | remove-from-response | Remove the HTTP header from response. + required: false + choices: ["add-to-request", "add-to-response", "remove-from-request", "remove-from-response"] + + headers_content: + description: + - HTTP header's content. + required: false + + headers_name: + description: + - HTTP forwarded header name. + required: false + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_proxy: + name: "Ansible_Web_Proxy_Profile" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_proxy: + name: "Ansible_Web_Proxy_Profile" + mode: "set" + header_client_ip: "pass" + header_front_end_https: "add" + header_via_request: "remove" + header_via_response: "pass" + header_x_authenticated_groups: "add" + header_x_authenticated_user: "remove" + strip_encoding: "enable" + log_header_change: "enable" + header_x_forwarded_for: "pass" + headers_action: "add-to-request" + headers_content: "test" + headers_name: "test_header" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_web_proxy_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/web-proxy/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/web-proxy/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + strip_encoding=dict(required=False, type="str", choices=["disable", "enable"]), + name=dict(required=False, type="str"), + log_header_change=dict(required=False, type="str", choices=["disable", "enable"]), + header_x_forwarded_for=dict(required=False, type="str", choices=["pass", "add", "remove"]), + header_x_authenticated_user=dict(required=False, type="str", choices=["pass", "add", "remove"]), + header_x_authenticated_groups=dict(required=False, type="str", choices=["pass", "add", "remove"]), + header_via_response=dict(required=False, type="str", choices=["pass", "add", "remove"]), + header_via_request=dict(required=False, type="str", choices=["pass", "add", "remove"]), + header_front_end_https=dict(required=False, type="str", choices=["pass", "add", "remove"]), + header_client_ip=dict(required=False, type="str", choices=["pass", "add", "remove"]), + headers=dict(required=False, type="list"), + headers_action=dict(required=False, type="str", choices=["add-to-request", "add-to-response", + "remove-from-request", "remove-from-response"]), + headers_content=dict(required=False, type="str"), + headers_name=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "strip-encoding": module.params["strip_encoding"], + "name": module.params["name"], + "log-header-change": module.params["log_header_change"], + "header-x-forwarded-for": module.params["header_x_forwarded_for"], + "header-x-authenticated-user": module.params["header_x_authenticated_user"], + "header-x-authenticated-groups": module.params["header_x_authenticated_groups"], + "header-via-response": module.params["header_via_response"], + "header-via-request": module.params["header_via_request"], + "header-front-end-https": module.params["header_front_end_https"], + "header-client-ip": module.params["header_client_ip"], + "headers": { + "action": module.params["headers_action"], + "content": module.params["headers_content"], + "name": module.params["headers_name"], + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['headers'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + module.paramgram = paramgram + + results = DEFAULT_RESULT_OBJ + try: + results = fmgr_web_proxy_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_spam.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_spam.py new file mode 100644 index 00000000..ac5e918a --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_spam.py @@ -0,0 +1,607 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_spam +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: spam filter profile for FMG +description: + - Manage spam filter security profiles within FortiManager via API + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + spam_rbl_table: + description: + - Anti-spam DNSBL table ID. + required: false + + spam_mheader_table: + description: + - Anti-spam MIME header table ID. + required: false + + spam_log_fortiguard_response: + description: + - Enable/disable logging FortiGuard spam response. + required: false + choices: + - disable + - enable + + spam_log: + description: + - Enable/disable spam logging for email filtering. + required: false + choices: + - disable + - enable + + spam_iptrust_table: + description: + - Anti-spam IP trust table ID. + required: false + + spam_filtering: + description: + - Enable/disable spam filtering. + required: false + choices: + - disable + - enable + + spam_bword_threshold: + description: + - Spam banned word threshold. + required: false + + spam_bword_table: + description: + - Anti-spam banned word table ID. + required: false + + spam_bwl_table: + description: + - Anti-spam black/white list table ID. + required: false + + replacemsg_group: + description: + - Replacement message group. + required: false + + options: + description: + - None + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - bannedword + - spamfsip + - spamfssubmit + - spamfschksum + - spamfsurl + - spamhelodns + - spamraddrdns + - spamrbl + - spamhdrcheck + - spamfsphish + - spambwl + + name: + description: + - Profile name. + required: false + + flow_based: + description: + - Enable/disable flow-based spam filtering. + required: false + choices: + - disable + - enable + + external: + description: + - Enable/disable external Email inspection. + required: false + choices: + - disable + - enable + + comment: + description: + - Comment. + required: false + + gmail: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + gmail_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + imap: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + imap_action: + description: + - Action for spam email. + required: false + choices: + - pass + - tag + + imap_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + imap_tag_msg: + description: + - Subject text or header added to spam email. + required: false + + imap_tag_type: + description: + - Tag subject or header for spam email. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - subject + - header + - spaminfo + + mapi: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + mapi_action: + description: + - Action for spam email. + required: false + choices: + - pass + - discard + + mapi_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + msn_hotmail: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + msn_hotmail_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + pop3: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + pop3_action: + description: + - Action for spam email. + required: false + choices: + - pass + - tag + + pop3_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + pop3_tag_msg: + description: + - Subject text or header added to spam email. + required: false + + pop3_tag_type: + description: + - Tag subject or header for spam email. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - subject + - header + - spaminfo + + smtp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + smtp_action: + description: + - Action for spam email. + required: false + choices: + - pass + - tag + - discard + + smtp_hdrip: + description: + - Enable/disable SMTP email header IP checks for spamfsip, spamrbl and spambwl filters. + required: false + choices: + - disable + - enable + + smtp_local_override: + description: + - Enable/disable local filter to override SMTP remote check result. + required: false + choices: + - disable + - enable + + smtp_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + smtp_tag_msg: + description: + - Subject text or header added to spam email. + required: false + + smtp_tag_type: + description: + - Tag subject or header for spam email. + - FLAG Based Options. Specify multiple in list form. + required: false + choices: + - subject + - header + - spaminfo + + yahoo_mail: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + yahoo_mail_log: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_spam: + name: "Ansible_Spam_Filter_Profile" + mode: "delete" + + - name: Create FMGR_SPAMFILTER_PROFILE + community.fortios.fmgr_secprof_spam: + host: "{{ inventory_hostname }}" + username: "{{ username }}" + password: "{{ password }}" + mode: "set" + adom: "root" + spam_log_fortiguard_response: "enable" + spam_iptrust_table: + spam_filtering: "enable" + spam_bword_threshold: 10 + options: ["bannedword", "spamfsip", "spamfsurl", "spamrbl", "spamfsphish", "spambwl"] + name: "Ansible_Spam_Filter_Profile" + flow_based: "enable" + external: "enable" + comment: "Created by Ansible" + gmail_log: "enable" + spam_log: "enable" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + +############### +# START METHODS +############### + + +def fmgr_spamfilter_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/spamfilter/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/spamfilter/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + spam_rbl_table=dict(required=False, type="str"), + spam_mheader_table=dict(required=False, type="str"), + spam_log_fortiguard_response=dict(required=False, type="str", choices=["disable", "enable"]), + spam_log=dict(required=False, type="str", choices=["disable", "enable"]), + spam_iptrust_table=dict(required=False, type="str"), + spam_filtering=dict(required=False, type="str", choices=["disable", "enable"]), + spam_bword_threshold=dict(required=False, type="int"), + spam_bword_table=dict(required=False, type="str"), + spam_bwl_table=dict(required=False, type="str"), + replacemsg_group=dict(required=False, type="str"), + options=dict(required=False, type="list", choices=["bannedword", + "spamfsip", + "spamfssubmit", + "spamfschksum", + "spamfsurl", + "spamhelodns", + "spamraddrdns", + "spamrbl", + "spamhdrcheck", + "spamfsphish", + "spambwl"]), + name=dict(required=False, type="str"), + flow_based=dict(required=False, type="str", choices=["disable", "enable"]), + external=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + gmail=dict(required=False, type="dict"), + gmail_log=dict(required=False, type="str", choices=["disable", "enable"]), + imap=dict(required=False, type="dict"), + imap_action=dict(required=False, type="str", choices=["pass", "tag"]), + imap_log=dict(required=False, type="str", choices=["disable", "enable"]), + imap_tag_msg=dict(required=False, type="str"), + imap_tag_type=dict(required=False, type="str", choices=["subject", "header", "spaminfo"]), + mapi=dict(required=False, type="dict"), + mapi_action=dict(required=False, type="str", choices=["pass", "discard"]), + mapi_log=dict(required=False, type="str", choices=["disable", "enable"]), + msn_hotmail=dict(required=False, type="dict"), + msn_hotmail_log=dict(required=False, type="str", choices=["disable", "enable"]), + pop3=dict(required=False, type="dict"), + pop3_action=dict(required=False, type="str", choices=["pass", "tag"]), + pop3_log=dict(required=False, type="str", choices=["disable", "enable"]), + pop3_tag_msg=dict(required=False, type="str"), + pop3_tag_type=dict(required=False, type="str", choices=["subject", "header", "spaminfo"]), + smtp=dict(required=False, type="dict"), + smtp_action=dict(required=False, type="str", choices=["pass", "tag", "discard"]), + smtp_hdrip=dict(required=False, type="str", choices=["disable", "enable"]), + smtp_local_override=dict(required=False, type="str", choices=["disable", "enable"]), + smtp_log=dict(required=False, type="str", choices=["disable", "enable"]), + smtp_tag_msg=dict(required=False, type="str"), + smtp_tag_type=dict(required=False, type="str", choices=["subject", "header", "spaminfo"]), + yahoo_mail=dict(required=False, type="dict"), + yahoo_mail_log=dict(required=False, type="str", choices=["disable", "enable"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "spam-rbl-table": module.params["spam_rbl_table"], + "spam-mheader-table": module.params["spam_mheader_table"], + "spam-log-fortiguard-response": module.params["spam_log_fortiguard_response"], + "spam-log": module.params["spam_log"], + "spam-iptrust-table": module.params["spam_iptrust_table"], + "spam-filtering": module.params["spam_filtering"], + "spam-bword-threshold": module.params["spam_bword_threshold"], + "spam-bword-table": module.params["spam_bword_table"], + "spam-bwl-table": module.params["spam_bwl_table"], + "replacemsg-group": module.params["replacemsg_group"], + "options": module.params["options"], + "name": module.params["name"], + "flow-based": module.params["flow_based"], + "external": module.params["external"], + "comment": module.params["comment"], + "gmail": { + "log": module.params["gmail_log"], + }, + "imap": { + "action": module.params["imap_action"], + "log": module.params["imap_log"], + "tag-msg": module.params["imap_tag_msg"], + "tag-type": module.params["imap_tag_type"], + }, + "mapi": { + "action": module.params["mapi_action"], + "log": module.params["mapi_log"], + }, + "msn-hotmail": { + "log": module.params["msn_hotmail_log"], + }, + "pop3": { + "action": module.params["pop3_action"], + "log": module.params["pop3_log"], + "tag-msg": module.params["pop3_tag_msg"], + "tag-type": module.params["pop3_tag_type"], + }, + "smtp": { + "action": module.params["smtp_action"], + "hdrip": module.params["smtp_hdrip"], + "local-override": module.params["smtp_local_override"], + "log": module.params["smtp_log"], + "tag-msg": module.params["smtp_tag_msg"], + "tag-type": module.params["smtp_tag_type"], + }, + "yahoo-mail": { + "log": module.params["yahoo_mail_log"], + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['gmail', 'imap', 'mapi', 'msn-hotmail', 'pop3', 'smtp', 'yahoo-mail'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + try: + + results = fmgr_spamfilter_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_ssl_ssh.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_ssl_ssh.py new file mode 100644 index 00000000..1e9a0f7d --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_ssl_ssh.py @@ -0,0 +1,954 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_ssl_ssh +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage SSL and SSH security profiles in FortiManager +description: + - Manage SSL and SSH security profiles in FortiManager via the FMG API + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + whitelist: + description: + - Enable/disable exempting servers by FortiGuard whitelist. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + use_ssl_server: + description: + - Enable/disable the use of SSL server table for SSL offloading. + - choice | disable | Don't use SSL server configuration. + - choice | enable | Use SSL server configuration. + required: false + choices: ["disable", "enable"] + + untrusted_caname: + description: + - Untrusted CA certificate used by SSL Inspection. + required: false + + ssl_exemptions_log: + description: + - Enable/disable logging SSL exemptions. + - choice | disable | Disable logging SSL exemptions. + - choice | enable | Enable logging SSL exemptions. + required: false + choices: ["disable", "enable"] + + ssl_anomalies_log: + description: + - Enable/disable logging SSL anomalies. + - choice | disable | Disable logging SSL anomalies. + - choice | enable | Enable logging SSL anomalies. + required: false + choices: ["disable", "enable"] + + server_cert_mode: + description: + - Re-sign or replace the server's certificate. + - choice | re-sign | Multiple clients connecting to multiple servers. + - choice | replace | Protect an SSL server. + required: false + choices: ["re-sign", "replace"] + + server_cert: + description: + - Certificate used by SSL Inspection to replace server certificate. + required: false + + rpc_over_https: + description: + - Enable/disable inspection of RPC over HTTPS. + - choice | disable | Disable inspection of RPC over HTTPS. + - choice | enable | Enable inspection of RPC over HTTPS. + required: false + choices: ["disable", "enable"] + + name: + description: + - Name. + required: false + + mapi_over_https: + description: + - Enable/disable inspection of MAPI over HTTPS. + - choice | disable | Disable inspection of MAPI over HTTPS. + - choice | enable | Enable inspection of MAPI over HTTPS. + required: false + choices: ["disable", "enable"] + + comment: + description: + - Optional comments. + required: false + + caname: + description: + - CA certificate used by SSL Inspection. + required: false + + ftps: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ftps_allow_invalid_server_cert: + description: + - When enabled, allows SSL sessions whose server certificate validation failed. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ftps_client_cert_request: + description: + - Action based on client certificate request failure. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ftps_ports: + description: + - Ports to use for scanning (1 - 65535, default = 443). + required: false + + ftps_status: + description: + - Configure protocol inspection status. + - choice | disable | Disable. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "deep-inspection"] + + ftps_unsupported_ssl: + description: + - Action based on the SSL encryption used being unsupported. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ftps_untrusted_cert: + description: + - Allow, ignore, or block the untrusted SSL session server certificate. + - choice | allow | Allow the untrusted server certificate. + - choice | block | Block the connection when an untrusted server certificate is detected. + - choice | ignore | Always take the server certificate as trusted. + required: false + choices: ["allow", "block", "ignore"] + + https: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + https_allow_invalid_server_cert: + description: + - When enabled, allows SSL sessions whose server certificate validation failed. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + https_client_cert_request: + description: + - Action based on client certificate request failure. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + https_ports: + description: + - Ports to use for scanning (1 - 65535, default = 443). + required: false + + https_status: + description: + - Configure protocol inspection status. + - choice | disable | Disable. + - choice | certificate-inspection | Inspect SSL handshake only. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "certificate-inspection", "deep-inspection"] + + https_unsupported_ssl: + description: + - Action based on the SSL encryption used being unsupported. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + https_untrusted_cert: + description: + - Allow, ignore, or block the untrusted SSL session server certificate. + - choice | allow | Allow the untrusted server certificate. + - choice | block | Block the connection when an untrusted server certificate is detected. + - choice | ignore | Always take the server certificate as trusted. + required: false + choices: ["allow", "block", "ignore"] + + imaps: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + imaps_allow_invalid_server_cert: + description: + - When enabled, allows SSL sessions whose server certificate validation failed. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + imaps_client_cert_request: + description: + - Action based on client certificate request failure. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + imaps_ports: + description: + - Ports to use for scanning (1 - 65535, default = 443). + required: false + + imaps_status: + description: + - Configure protocol inspection status. + - choice | disable | Disable. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "deep-inspection"] + + imaps_unsupported_ssl: + description: + - Action based on the SSL encryption used being unsupported. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + imaps_untrusted_cert: + description: + - Allow, ignore, or block the untrusted SSL session server certificate. + - choice | allow | Allow the untrusted server certificate. + - choice | block | Block the connection when an untrusted server certificate is detected. + - choice | ignore | Always take the server certificate as trusted. + required: false + choices: ["allow", "block", "ignore"] + + pop3s: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + pop3s_allow_invalid_server_cert: + description: + - When enabled, allows SSL sessions whose server certificate validation failed. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + pop3s_client_cert_request: + description: + - Action based on client certificate request failure. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + pop3s_ports: + description: + - Ports to use for scanning (1 - 65535, default = 443). + required: false + + pop3s_status: + description: + - Configure protocol inspection status. + - choice | disable | Disable. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "deep-inspection"] + + pop3s_unsupported_ssl: + description: + - Action based on the SSL encryption used being unsupported. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + pop3s_untrusted_cert: + description: + - Allow, ignore, or block the untrusted SSL session server certificate. + - choice | allow | Allow the untrusted server certificate. + - choice | block | Block the connection when an untrusted server certificate is detected. + - choice | ignore | Always take the server certificate as trusted. + required: false + choices: ["allow", "block", "ignore"] + + smtps: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + smtps_allow_invalid_server_cert: + description: + - When enabled, allows SSL sessions whose server certificate validation failed. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + smtps_client_cert_request: + description: + - Action based on client certificate request failure. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + smtps_ports: + description: + - Ports to use for scanning (1 - 65535, default = 443). + required: false + + smtps_status: + description: + - Configure protocol inspection status. + - choice | disable | Disable. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "deep-inspection"] + + smtps_unsupported_ssl: + description: + - Action based on the SSL encryption used being unsupported. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + smtps_untrusted_cert: + description: + - Allow, ignore, or block the untrusted SSL session server certificate. + - choice | allow | Allow the untrusted server certificate. + - choice | block | Block the connection when an untrusted server certificate is detected. + - choice | ignore | Always take the server certificate as trusted. + required: false + choices: ["allow", "block", "ignore"] + + ssh: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ssh_inspect_all: + description: + - Level of SSL inspection. + - choice | disable | Disable. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "deep-inspection"] + + ssh_ports: + description: + - Ports to use for scanning (1 - 65535, default = 443). + required: false + + ssh_ssh_algorithm: + description: + - Relative strength of encryption algorithms accepted during negotiation. + - choice | compatible | Allow a broader set of encryption algorithms for best compatibility. + - choice | high-encryption | Allow only AES-CTR, AES-GCM ciphers and high encryption algorithms. + required: false + choices: ["compatible", "high-encryption"] + + ssh_ssh_policy_check: + description: + - Enable/disable SSH policy check. + - choice | disable | Disable SSH policy check. + - choice | enable | Enable SSH policy check. + required: false + choices: ["disable", "enable"] + + ssh_ssh_tun_policy_check: + description: + - Enable/disable SSH tunnel policy check. + - choice | disable | Disable SSH tunnel policy check. + - choice | enable | Enable SSH tunnel policy check. + required: false + choices: ["disable", "enable"] + + ssh_status: + description: + - Configure protocol inspection status. + - choice | disable | Disable. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "deep-inspection"] + + ssh_unsupported_version: + description: + - Action based on SSH version being unsupported. + - choice | block | Block. + - choice | bypass | Bypass. + required: false + choices: ["block", "bypass"] + + ssl: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ssl_allow_invalid_server_cert: + description: + - When enabled, allows SSL sessions whose server certificate validation failed. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ssl_client_cert_request: + description: + - Action based on client certificate request failure. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_inspect_all: + description: + - Level of SSL inspection. + - choice | disable | Disable. + - choice | certificate-inspection | Inspect SSL handshake only. + - choice | deep-inspection | Full SSL inspection. + required: false + choices: ["disable", "certificate-inspection", "deep-inspection"] + + ssl_unsupported_ssl: + description: + - Action based on the SSL encryption used being unsupported. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_untrusted_cert: + description: + - Allow, ignore, or block the untrusted SSL session server certificate. + - choice | allow | Allow the untrusted server certificate. + - choice | block | Block the connection when an untrusted server certificate is detected. + - choice | ignore | Always take the server certificate as trusted. + required: false + choices: ["allow", "block", "ignore"] + + ssl_exempt: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ssl_exempt_address: + description: + - IPv4 address object. + required: false + + ssl_exempt_address6: + description: + - IPv6 address object. + required: false + + ssl_exempt_fortiguard_category: + description: + - FortiGuard category ID. + required: false + + ssl_exempt_regex: + description: + - Exempt servers by regular expression. + required: false + + ssl_exempt_type: + description: + - Type of address object (IPv4 or IPv6) or FortiGuard category. + - choice | fortiguard-category | FortiGuard category. + - choice | address | Firewall IPv4 address. + - choice | address6 | Firewall IPv6 address. + - choice | wildcard-fqdn | Fully Qualified Domain Name with wildcard characters. + - choice | regex | Regular expression FQDN. + required: false + choices: ["fortiguard-category", "address", "address6", "wildcard-fqdn", "regex"] + + ssl_exempt_wildcard_fqdn: + description: + - Exempt servers by wildcard FQDN. + required: false + + ssl_server: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ssl_server_ftps_client_cert_request: + description: + - Action based on client certificate request failure during the FTPS handshake. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_server_https_client_cert_request: + description: + - Action based on client certificate request failure during the HTTPS handshake. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_server_imaps_client_cert_request: + description: + - Action based on client certificate request failure during the IMAPS handshake. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_server_ip: + description: + - IPv4 address of the SSL server. + required: false + + ssl_server_pop3s_client_cert_request: + description: + - Action based on client certificate request failure during the POP3S handshake. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_server_smtps_client_cert_request: + description: + - Action based on client certificate request failure during the SMTPS handshake. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + ssl_server_ssl_other_client_cert_request: + description: + - Action based on client certificate request failure during an SSL protocol handshake. + - choice | bypass | Bypass. + - choice | inspect | Inspect. + - choice | block | Block. + required: false + choices: ["bypass", "inspect", "block"] + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_ssl_ssh: + name: Ansible_SSL_SSH_Profile + mode: delete + + - name: CREATE Profile + community.fortios.fmgr_secprof_ssl_ssh: + name: Ansible_SSL_SSH_Profile + comment: "Created by Ansible Module TEST" + mode: set + mapi_over_https: enable + rpc_over_https: enable + server_cert_mode: replace + ssl_anomalies_log: enable + ssl_exemptions_log: enable + use_ssl_server: enable + whitelist: enable +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + +############### +# START METHODS +############### + + +def fmgr_firewall_ssl_ssh_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/firewall/ssl-ssh-profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/firewall/ssl-ssh-profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + whitelist=dict(required=False, type="str", choices=["disable", "enable"]), + use_ssl_server=dict(required=False, type="str", choices=["disable", "enable"]), + untrusted_caname=dict(required=False, type="str"), + ssl_exemptions_log=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_anomalies_log=dict(required=False, type="str", choices=["disable", "enable"]), + server_cert_mode=dict(required=False, type="str", choices=["re-sign", "replace"]), + server_cert=dict(required=False, type="str"), + rpc_over_https=dict(required=False, type="str", choices=["disable", "enable"]), + name=dict(required=False, type="str"), + mapi_over_https=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + caname=dict(required=False, type="str"), + ftps=dict(required=False, type="list"), + ftps_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]), + ftps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ftps_ports=dict(required=False, type="str"), + ftps_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]), + ftps_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ftps_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]), + https=dict(required=False, type="list"), + https_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]), + https_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + https_ports=dict(required=False, type="str"), + https_status=dict(required=False, type="str", choices=["disable", "certificate-inspection", "deep-inspection"]), + https_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + https_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]), + imaps=dict(required=False, type="list"), + imaps_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]), + imaps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + imaps_ports=dict(required=False, type="str"), + imaps_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]), + imaps_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + imaps_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]), + pop3s=dict(required=False, type="list"), + pop3s_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]), + pop3s_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + pop3s_ports=dict(required=False, type="str"), + pop3s_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]), + pop3s_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + pop3s_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]), + smtps=dict(required=False, type="list"), + smtps_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]), + smtps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + smtps_ports=dict(required=False, type="str"), + smtps_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]), + smtps_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + smtps_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]), + ssh=dict(required=False, type="list"), + ssh_inspect_all=dict(required=False, type="str", choices=["disable", "deep-inspection"]), + ssh_ports=dict(required=False, type="str"), + ssh_ssh_algorithm=dict(required=False, type="str", choices=["compatible", "high-encryption"]), + ssh_ssh_policy_check=dict(required=False, type="str", choices=["disable", "enable"]), + ssh_ssh_tun_policy_check=dict(required=False, type="str", choices=["disable", "enable"]), + ssh_status=dict(required=False, type="str", choices=["disable", "deep-inspection"]), + ssh_unsupported_version=dict(required=False, type="str", choices=["block", "bypass"]), + ssl=dict(required=False, type="list"), + ssl_allow_invalid_server_cert=dict(required=False, type="str", choices=["disable", "enable"]), + ssl_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_inspect_all=dict(required=False, type="str", choices=["disable", "certificate-inspection", + "deep-inspection"]), + ssl_unsupported_ssl=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_untrusted_cert=dict(required=False, type="str", choices=["allow", "block", "ignore"]), + ssl_exempt=dict(required=False, type="list"), + ssl_exempt_address=dict(required=False, type="str"), + ssl_exempt_address6=dict(required=False, type="str"), + ssl_exempt_fortiguard_category=dict(required=False, type="str"), + ssl_exempt_regex=dict(required=False, type="str"), + ssl_exempt_type=dict(required=False, type="str", choices=["fortiguard-category", "address", "address6", + "wildcard-fqdn", "regex"]), + ssl_exempt_wildcard_fqdn=dict(required=False, type="str"), + ssl_server=dict(required=False, type="list"), + ssl_server_ftps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_server_https_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_server_imaps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_server_ip=dict(required=False, type="str"), + ssl_server_pop3s_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_server_smtps_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", "block"]), + ssl_server_ssl_other_client_cert_request=dict(required=False, type="str", choices=["bypass", "inspect", + "block"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "whitelist": module.params["whitelist"], + "use-ssl-server": module.params["use_ssl_server"], + "untrusted-caname": module.params["untrusted_caname"], + "ssl-exemptions-log": module.params["ssl_exemptions_log"], + "ssl-anomalies-log": module.params["ssl_anomalies_log"], + "server-cert-mode": module.params["server_cert_mode"], + "server-cert": module.params["server_cert"], + "rpc-over-https": module.params["rpc_over_https"], + "name": module.params["name"], + "mapi-over-https": module.params["mapi_over_https"], + "comment": module.params["comment"], + "caname": module.params["caname"], + "ftps": { + "allow-invalid-server-cert": module.params["ftps_allow_invalid_server_cert"], + "client-cert-request": module.params["ftps_client_cert_request"], + "ports": module.params["ftps_ports"], + "status": module.params["ftps_status"], + "unsupported-ssl": module.params["ftps_unsupported_ssl"], + "untrusted-cert": module.params["ftps_untrusted_cert"], + }, + "https": { + "allow-invalid-server-cert": module.params["https_allow_invalid_server_cert"], + "client-cert-request": module.params["https_client_cert_request"], + "ports": module.params["https_ports"], + "status": module.params["https_status"], + "unsupported-ssl": module.params["https_unsupported_ssl"], + "untrusted-cert": module.params["https_untrusted_cert"], + }, + "imaps": { + "allow-invalid-server-cert": module.params["imaps_allow_invalid_server_cert"], + "client-cert-request": module.params["imaps_client_cert_request"], + "ports": module.params["imaps_ports"], + "status": module.params["imaps_status"], + "unsupported-ssl": module.params["imaps_unsupported_ssl"], + "untrusted-cert": module.params["imaps_untrusted_cert"], + }, + "pop3s": { + "allow-invalid-server-cert": module.params["pop3s_allow_invalid_server_cert"], + "client-cert-request": module.params["pop3s_client_cert_request"], + "ports": module.params["pop3s_ports"], + "status": module.params["pop3s_status"], + "unsupported-ssl": module.params["pop3s_unsupported_ssl"], + "untrusted-cert": module.params["pop3s_untrusted_cert"], + }, + "smtps": { + "allow-invalid-server-cert": module.params["smtps_allow_invalid_server_cert"], + "client-cert-request": module.params["smtps_client_cert_request"], + "ports": module.params["smtps_ports"], + "status": module.params["smtps_status"], + "unsupported-ssl": module.params["smtps_unsupported_ssl"], + "untrusted-cert": module.params["smtps_untrusted_cert"], + }, + "ssh": { + "inspect-all": module.params["ssh_inspect_all"], + "ports": module.params["ssh_ports"], + "ssh-algorithm": module.params["ssh_ssh_algorithm"], + "ssh-policy-check": module.params["ssh_ssh_policy_check"], + "ssh-tun-policy-check": module.params["ssh_ssh_tun_policy_check"], + "status": module.params["ssh_status"], + "unsupported-version": module.params["ssh_unsupported_version"], + }, + "ssl": { + "allow-invalid-server-cert": module.params["ssl_allow_invalid_server_cert"], + "client-cert-request": module.params["ssl_client_cert_request"], + "inspect-all": module.params["ssl_inspect_all"], + "unsupported-ssl": module.params["ssl_unsupported_ssl"], + "untrusted-cert": module.params["ssl_untrusted_cert"], + }, + "ssl-exempt": { + "address": module.params["ssl_exempt_address"], + "address6": module.params["ssl_exempt_address6"], + "fortiguard-category": module.params["ssl_exempt_fortiguard_category"], + "regex": module.params["ssl_exempt_regex"], + "type": module.params["ssl_exempt_type"], + "wildcard-fqdn": module.params["ssl_exempt_wildcard_fqdn"], + }, + "ssl-server": { + "ftps-client-cert-request": module.params["ssl_server_ftps_client_cert_request"], + "https-client-cert-request": module.params["ssl_server_https_client_cert_request"], + "imaps-client-cert-request": module.params["ssl_server_imaps_client_cert_request"], + "ip": module.params["ssl_server_ip"], + "pop3s-client-cert-request": module.params["ssl_server_pop3s_client_cert_request"], + "smtps-client-cert-request": module.params["ssl_server_smtps_client_cert_request"], + "ssl-other-client-cert-request": module.params["ssl_server_ssl_other_client_cert_request"], + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['ftps', 'https', 'imaps', 'pop3s', 'smtps', 'ssh', 'ssl', 'ssl-exempt', 'ssl-server'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + + try: + + results = fmgr_firewall_ssl_ssh_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_voip.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_voip.py new file mode 100644 index 00000000..31b71288 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_voip.py @@ -0,0 +1,1198 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_voip +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: VOIP security profiles in FMG +description: + - Manage VOIP security profiles in FortiManager via API + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + name: + description: + - Profile name. + required: false + + comment: + description: + - Comment. + required: false + + sccp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + sccp_block_mcast: + description: + - Enable/disable block multicast RTP connections. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sccp_log_call_summary: + description: + - Enable/disable log summary of SCCP calls. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sccp_log_violations: + description: + - Enable/disable logging of SCCP violations. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sccp_max_calls: + description: + - Maximum calls per minute per SCCP client (max 65535). + required: false + + sccp_status: + description: + - Enable/disable SCCP. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sccp_verify_header: + description: + - Enable/disable verify SCCP header content. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + sip_ack_rate: + description: + - ACK request rate limit (per second, per policy). + required: false + + sip_block_ack: + description: + - Enable/disable block ACK requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_bye: + description: + - Enable/disable block BYE requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_cancel: + description: + - Enable/disable block CANCEL requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_geo_red_options: + description: + - Enable/disable block OPTIONS requests, but OPTIONS requests still notify for redundancy. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_info: + description: + - Enable/disable block INFO requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_invite: + description: + - Enable/disable block INVITE requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_long_lines: + description: + - Enable/disable block requests with headers exceeding max-line-length. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_message: + description: + - Enable/disable block MESSAGE requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_notify: + description: + - Enable/disable block NOTIFY requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_options: + description: + - Enable/disable block OPTIONS requests and no OPTIONS as notifying message for redundancy either. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_prack: + description: + - Enable/disable block prack requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_publish: + description: + - Enable/disable block PUBLISH requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_refer: + description: + - Enable/disable block REFER requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_register: + description: + - Enable/disable block REGISTER requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_subscribe: + description: + - Enable/disable block SUBSCRIBE requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_unknown: + description: + - Block unrecognized SIP requests (enabled by default). + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_block_update: + description: + - Enable/disable block UPDATE requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_bye_rate: + description: + - BYE request rate limit (per second, per policy). + required: false + + sip_call_keepalive: + description: + - Continue tracking calls with no RTP for this many minutes. + required: false + + sip_cancel_rate: + description: + - CANCEL request rate limit (per second, per policy). + required: false + + sip_contact_fixup: + description: + - Fixup contact anyway even if contact's IP|port doesn't match session's IP|port. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_hnt_restrict_source_ip: + description: + - Enable/disable restrict RTP source IP to be the same as SIP source IP when HNT is enabled. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_hosted_nat_traversal: + description: + - Hosted NAT Traversal (HNT). + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_info_rate: + description: + - INFO request rate limit (per second, per policy). + required: false + + sip_invite_rate: + description: + - INVITE request rate limit (per second, per policy). + required: false + + sip_ips_rtp: + description: + - Enable/disable allow IPS on RTP. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_log_call_summary: + description: + - Enable/disable logging of SIP call summary. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_log_violations: + description: + - Enable/disable logging of SIP violations. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_malformed_header_allow: + description: + - Action for malformed Allow header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_call_id: + description: + - Action for malformed Call-ID header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_contact: + description: + - Action for malformed Contact header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_content_length: + description: + - Action for malformed Content-Length header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_content_type: + description: + - Action for malformed Content-Type header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_cseq: + description: + - Action for malformed CSeq header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_expires: + description: + - Action for malformed Expires header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_from: + description: + - Action for malformed From header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_max_forwards: + description: + - Action for malformed Max-Forwards header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_p_asserted_identity: + description: + - Action for malformed P-Asserted-Identity header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_rack: + description: + - Action for malformed RAck header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_record_route: + description: + - Action for malformed Record-Route header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_route: + description: + - Action for malformed Route header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_rseq: + description: + - Action for malformed RSeq header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_a: + description: + - Action for malformed SDP a line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_b: + description: + - Action for malformed SDP b line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_c: + description: + - Action for malformed SDP c line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_i: + description: + - Action for malformed SDP i line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_k: + description: + - Action for malformed SDP k line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_m: + description: + - Action for malformed SDP m line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_o: + description: + - Action for malformed SDP o line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_r: + description: + - Action for malformed SDP r line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_s: + description: + - Action for malformed SDP s line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_t: + description: + - Action for malformed SDP t line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_v: + description: + - Action for malformed SDP v line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_sdp_z: + description: + - Action for malformed SDP z line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_to: + description: + - Action for malformed To header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_header_via: + description: + - Action for malformed VIA header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_malformed_request_line: + description: + - Action for malformed request line. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_max_body_length: + description: + - Maximum SIP message body length (0 meaning no limit). + required: false + + sip_max_dialogs: + description: + - Maximum number of concurrent calls/dialogs (per policy). + required: false + + sip_max_idle_dialogs: + description: + - Maximum number established but idle dialogs to retain (per policy). + required: false + + sip_max_line_length: + description: + - Maximum SIP header line length (78-4096). + required: false + + sip_message_rate: + description: + - MESSAGE request rate limit (per second, per policy). + required: false + + sip_nat_trace: + description: + - Enable/disable preservation of original IP in SDP i line. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_no_sdp_fixup: + description: + - Enable/disable no SDP fix-up. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_notify_rate: + description: + - NOTIFY request rate limit (per second, per policy). + required: false + + sip_open_contact_pinhole: + description: + - Enable/disable open pinhole for non-REGISTER Contact port. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_open_record_route_pinhole: + description: + - Enable/disable open pinhole for Record-Route port. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_open_register_pinhole: + description: + - Enable/disable open pinhole for REGISTER Contact port. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_open_via_pinhole: + description: + - Enable/disable open pinhole for Via port. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_options_rate: + description: + - OPTIONS request rate limit (per second, per policy). + required: false + + sip_prack_rate: + description: + - PRACK request rate limit (per second, per policy). + required: false + + sip_preserve_override: + description: + - Override i line to preserve original IPS (default| append). + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_provisional_invite_expiry_time: + description: + - Expiry time for provisional INVITE (10 - 3600 sec). + required: false + + sip_publish_rate: + description: + - PUBLISH request rate limit (per second, per policy). + required: false + + sip_refer_rate: + description: + - REFER request rate limit (per second, per policy). + required: false + + sip_register_contact_trace: + description: + - Enable/disable trace original IP/port within the contact header of REGISTER requests. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_register_rate: + description: + - REGISTER request rate limit (per second, per policy). + required: false + + sip_rfc2543_branch: + description: + - Enable/disable support via branch compliant with RFC 2543. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_rtp: + description: + - Enable/disable create pinholes for RTP traffic to traverse firewall. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_ssl_algorithm: + description: + - Relative strength of encryption algorithms accepted in negotiation. + - choice | high | High encryption. Allow only AES and ChaCha. + - choice | medium | Medium encryption. Allow AES, ChaCha, 3DES, and RC4. + - choice | low | Low encryption. Allow AES, ChaCha, 3DES, RC4, and DES. + required: false + choices: ["high", "medium", "low"] + + sip_ssl_auth_client: + description: + - Require a client certificate and authenticate it with the peer/peergrp. + required: false + + sip_ssl_auth_server: + description: + - Authenticate the server's certificate with the peer/peergrp. + required: false + + sip_ssl_client_certificate: + description: + - Name of Certificate to offer to server if requested. + required: false + + sip_ssl_client_renegotiation: + description: + - Allow/block client renegotiation by server. + - choice | allow | Allow a SSL client to renegotiate. + - choice | deny | Abort any SSL connection that attempts to renegotiate. + - choice | secure | Reject any SSL connection that does not offer a RFC 5746 Secure Renegotiation Indication. + required: false + choices: ["allow", "deny", "secure"] + + sip_ssl_max_version: + description: + - Highest SSL/TLS version to negotiate. + - choice | ssl-3.0 | SSL 3.0. + - choice | tls-1.0 | TLS 1.0. + - choice | tls-1.1 | TLS 1.1. + - choice | tls-1.2 | TLS 1.2. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + sip_ssl_min_version: + description: + - Lowest SSL/TLS version to negotiate. + - choice | ssl-3.0 | SSL 3.0. + - choice | tls-1.0 | TLS 1.0. + - choice | tls-1.1 | TLS 1.1. + - choice | tls-1.2 | TLS 1.2. + required: false + choices: ["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"] + + sip_ssl_mode: + description: + - SSL/TLS mode for encryption & decryption of traffic. + - choice | off | No SSL. + - choice | full | Client to FortiGate and FortiGate to Server SSL. + required: false + choices: ["off", "full"] + + sip_ssl_pfs: + description: + - SSL Perfect Forward Secrecy. + - choice | require | PFS mandatory. + - choice | deny | PFS rejected. + - choice | allow | PFS allowed. + required: false + choices: ["require", "deny", "allow"] + + sip_ssl_send_empty_frags: + description: + - Send empty fragments to avoid attack on CBC IV (SSL 3.0 & TLS 1.0 only). + - choice | disable | Do not send empty fragments. + - choice | enable | Send empty fragments. + required: false + choices: ["disable", "enable"] + + sip_ssl_server_certificate: + description: + - Name of Certificate return to the client in every SSL connection. + required: false + + sip_status: + description: + - Enable/disable SIP. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_strict_register: + description: + - Enable/disable only allow the registrar to connect. + - choice | disable | Disable status. + - choice | enable | Enable status. + required: false + choices: ["disable", "enable"] + + sip_subscribe_rate: + description: + - SUBSCRIBE request rate limit (per second, per policy). + required: false + + sip_unknown_header: + description: + - Action for unknown SIP header. + - choice | pass | Bypass malformed messages. + - choice | discard | Discard malformed messages. + - choice | respond | Respond with error code. + required: false + choices: ["pass", "discard", "respond"] + + sip_update_rate: + description: + - UPDATE request rate limit (per second, per policy). + required: false + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_voip: + name: "Ansible_VOIP_Profile" + mode: "delete" + + - name: Create FMGR_VOIP_PROFILE + community.fortios.fmgr_secprof_voip: + mode: "set" + adom: "root" + name: "Ansible_VOIP_Profile" + comment: "Created by Ansible" + sccp: {block-mcast: "enable", log-call-summary: "enable", log-violations: "enable", status: "enable"} +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_voip_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/voip/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/voip/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + name=dict(required=False, type="str"), + comment=dict(required=False, type="str"), + sccp=dict(required=False, type="dict"), + sccp_block_mcast=dict(required=False, type="str", choices=["disable", "enable"]), + sccp_log_call_summary=dict(required=False, type="str", choices=["disable", "enable"]), + sccp_log_violations=dict(required=False, type="str", choices=["disable", "enable"]), + sccp_max_calls=dict(required=False, type="int"), + sccp_status=dict(required=False, type="str", choices=["disable", "enable"]), + sccp_verify_header=dict(required=False, type="str", choices=["disable", "enable"]), + sip=dict(required=False, type="dict"), + sip_ack_rate=dict(required=False, type="int"), + sip_block_ack=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_bye=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_cancel=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_geo_red_options=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_info=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_invite=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_long_lines=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_message=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_notify=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_options=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_prack=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_publish=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_refer=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_register=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_subscribe=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_unknown=dict(required=False, type="str", choices=["disable", "enable"]), + sip_block_update=dict(required=False, type="str", choices=["disable", "enable"]), + sip_bye_rate=dict(required=False, type="int"), + sip_call_keepalive=dict(required=False, type="int"), + sip_cancel_rate=dict(required=False, type="int"), + sip_contact_fixup=dict(required=False, type="str", choices=["disable", "enable"]), + sip_hnt_restrict_source_ip=dict(required=False, type="str", choices=["disable", "enable"]), + sip_hosted_nat_traversal=dict(required=False, type="str", choices=["disable", "enable"]), + sip_info_rate=dict(required=False, type="int"), + sip_invite_rate=dict(required=False, type="int"), + sip_ips_rtp=dict(required=False, type="str", choices=["disable", "enable"]), + sip_log_call_summary=dict(required=False, type="str", choices=["disable", "enable"]), + sip_log_violations=dict(required=False, type="str", choices=["disable", "enable"]), + sip_malformed_header_allow=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_call_id=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_contact=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_content_length=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_content_type=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_cseq=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_expires=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_from=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_max_forwards=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_p_asserted_identity=dict(required=False, type="str", choices=["pass", + "discard", + "respond"]), + sip_malformed_header_rack=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_record_route=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_route=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_rseq=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_a=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_b=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_c=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_i=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_k=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_m=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_o=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_r=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_s=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_t=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_v=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_sdp_z=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_to=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_header_via=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_malformed_request_line=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_max_body_length=dict(required=False, type="int"), + sip_max_dialogs=dict(required=False, type="int"), + sip_max_idle_dialogs=dict(required=False, type="int"), + sip_max_line_length=dict(required=False, type="int"), + sip_message_rate=dict(required=False, type="int"), + sip_nat_trace=dict(required=False, type="str", choices=["disable", "enable"]), + sip_no_sdp_fixup=dict(required=False, type="str", choices=["disable", "enable"]), + sip_notify_rate=dict(required=False, type="int"), + sip_open_contact_pinhole=dict(required=False, type="str", choices=["disable", "enable"]), + sip_open_record_route_pinhole=dict(required=False, type="str", choices=["disable", "enable"]), + sip_open_register_pinhole=dict(required=False, type="str", choices=["disable", "enable"]), + sip_open_via_pinhole=dict(required=False, type="str", choices=["disable", "enable"]), + sip_options_rate=dict(required=False, type="int"), + sip_prack_rate=dict(required=False, type="int"), + sip_preserve_override=dict(required=False, type="str", choices=["disable", "enable"]), + sip_provisional_invite_expiry_time=dict(required=False, type="int"), + sip_publish_rate=dict(required=False, type="int"), + sip_refer_rate=dict(required=False, type="int"), + sip_register_contact_trace=dict(required=False, type="str", choices=["disable", "enable"]), + sip_register_rate=dict(required=False, type="int"), + sip_rfc2543_branch=dict(required=False, type="str", choices=["disable", "enable"]), + sip_rtp=dict(required=False, type="str", choices=["disable", "enable"]), + sip_ssl_algorithm=dict(required=False, type="str", choices=["high", "medium", "low"]), + sip_ssl_auth_client=dict(required=False, type="str"), + sip_ssl_auth_server=dict(required=False, type="str"), + sip_ssl_client_certificate=dict(required=False, type="str"), + sip_ssl_client_renegotiation=dict(required=False, type="str", choices=["allow", "deny", "secure"]), + sip_ssl_max_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + sip_ssl_min_version=dict(required=False, type="str", choices=["ssl-3.0", "tls-1.0", "tls-1.1", "tls-1.2"]), + sip_ssl_mode=dict(required=False, type="str", choices=["off", "full"]), + sip_ssl_pfs=dict(required=False, type="str", choices=["require", "deny", "allow"]), + sip_ssl_send_empty_frags=dict(required=False, type="str", choices=["disable", "enable"]), + sip_ssl_server_certificate=dict(required=False, type="str"), + sip_status=dict(required=False, type="str", choices=["disable", "enable"]), + sip_strict_register=dict(required=False, type="str", choices=["disable", "enable"]), + sip_subscribe_rate=dict(required=False, type="int"), + sip_unknown_header=dict(required=False, type="str", choices=["pass", "discard", "respond"]), + sip_update_rate=dict(required=False, type="int"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "name": module.params["name"], + "comment": module.params["comment"], + "sccp": { + "block-mcast": module.params["sccp_block_mcast"], + "log-call-summary": module.params["sccp_log_call_summary"], + "log-violations": module.params["sccp_log_violations"], + "max-calls": module.params["sccp_max_calls"], + "status": module.params["sccp_status"], + "verify-header": module.params["sccp_verify_header"], + }, + "sip": { + "ack-rate": module.params["sip_ack_rate"], + "block-ack": module.params["sip_block_ack"], + "block-bye": module.params["sip_block_bye"], + "block-cancel": module.params["sip_block_cancel"], + "block-geo-red-options": module.params["sip_block_geo_red_options"], + "block-info": module.params["sip_block_info"], + "block-invite": module.params["sip_block_invite"], + "block-long-lines": module.params["sip_block_long_lines"], + "block-message": module.params["sip_block_message"], + "block-notify": module.params["sip_block_notify"], + "block-options": module.params["sip_block_options"], + "block-prack": module.params["sip_block_prack"], + "block-publish": module.params["sip_block_publish"], + "block-refer": module.params["sip_block_refer"], + "block-register": module.params["sip_block_register"], + "block-subscribe": module.params["sip_block_subscribe"], + "block-unknown": module.params["sip_block_unknown"], + "block-update": module.params["sip_block_update"], + "bye-rate": module.params["sip_bye_rate"], + "call-keepalive": module.params["sip_call_keepalive"], + "cancel-rate": module.params["sip_cancel_rate"], + "contact-fixup": module.params["sip_contact_fixup"], + "hnt-restrict-source-ip": module.params["sip_hnt_restrict_source_ip"], + "hosted-nat-traversal": module.params["sip_hosted_nat_traversal"], + "info-rate": module.params["sip_info_rate"], + "invite-rate": module.params["sip_invite_rate"], + "ips-rtp": module.params["sip_ips_rtp"], + "log-call-summary": module.params["sip_log_call_summary"], + "log-violations": module.params["sip_log_violations"], + "malformed-header-allow": module.params["sip_malformed_header_allow"], + "malformed-header-call-id": module.params["sip_malformed_header_call_id"], + "malformed-header-contact": module.params["sip_malformed_header_contact"], + "malformed-header-content-length": module.params["sip_malformed_header_content_length"], + "malformed-header-content-type": module.params["sip_malformed_header_content_type"], + "malformed-header-cseq": module.params["sip_malformed_header_cseq"], + "malformed-header-expires": module.params["sip_malformed_header_expires"], + "malformed-header-from": module.params["sip_malformed_header_from"], + "malformed-header-max-forwards": module.params["sip_malformed_header_max_forwards"], + "malformed-header-p-asserted-identity": module.params["sip_malformed_header_p_asserted_identity"], + "malformed-header-rack": module.params["sip_malformed_header_rack"], + "malformed-header-record-route": module.params["sip_malformed_header_record_route"], + "malformed-header-route": module.params["sip_malformed_header_route"], + "malformed-header-rseq": module.params["sip_malformed_header_rseq"], + "malformed-header-sdp-a": module.params["sip_malformed_header_sdp_a"], + "malformed-header-sdp-b": module.params["sip_malformed_header_sdp_b"], + "malformed-header-sdp-c": module.params["sip_malformed_header_sdp_c"], + "malformed-header-sdp-i": module.params["sip_malformed_header_sdp_i"], + "malformed-header-sdp-k": module.params["sip_malformed_header_sdp_k"], + "malformed-header-sdp-m": module.params["sip_malformed_header_sdp_m"], + "malformed-header-sdp-o": module.params["sip_malformed_header_sdp_o"], + "malformed-header-sdp-r": module.params["sip_malformed_header_sdp_r"], + "malformed-header-sdp-s": module.params["sip_malformed_header_sdp_s"], + "malformed-header-sdp-t": module.params["sip_malformed_header_sdp_t"], + "malformed-header-sdp-v": module.params["sip_malformed_header_sdp_v"], + "malformed-header-sdp-z": module.params["sip_malformed_header_sdp_z"], + "malformed-header-to": module.params["sip_malformed_header_to"], + "malformed-header-via": module.params["sip_malformed_header_via"], + "malformed-request-line": module.params["sip_malformed_request_line"], + "max-body-length": module.params["sip_max_body_length"], + "max-dialogs": module.params["sip_max_dialogs"], + "max-idle-dialogs": module.params["sip_max_idle_dialogs"], + "max-line-length": module.params["sip_max_line_length"], + "message-rate": module.params["sip_message_rate"], + "nat-trace": module.params["sip_nat_trace"], + "no-sdp-fixup": module.params["sip_no_sdp_fixup"], + "notify-rate": module.params["sip_notify_rate"], + "open-contact-pinhole": module.params["sip_open_contact_pinhole"], + "open-record-route-pinhole": module.params["sip_open_record_route_pinhole"], + "open-register-pinhole": module.params["sip_open_register_pinhole"], + "open-via-pinhole": module.params["sip_open_via_pinhole"], + "options-rate": module.params["sip_options_rate"], + "prack-rate": module.params["sip_prack_rate"], + "preserve-override": module.params["sip_preserve_override"], + "provisional-invite-expiry-time": module.params["sip_provisional_invite_expiry_time"], + "publish-rate": module.params["sip_publish_rate"], + "refer-rate": module.params["sip_refer_rate"], + "register-contact-trace": module.params["sip_register_contact_trace"], + "register-rate": module.params["sip_register_rate"], + "rfc2543-branch": module.params["sip_rfc2543_branch"], + "rtp": module.params["sip_rtp"], + "ssl-algorithm": module.params["sip_ssl_algorithm"], + "ssl-auth-client": module.params["sip_ssl_auth_client"], + "ssl-auth-server": module.params["sip_ssl_auth_server"], + "ssl-client-certificate": module.params["sip_ssl_client_certificate"], + "ssl-client-renegotiation": module.params["sip_ssl_client_renegotiation"], + "ssl-max-version": module.params["sip_ssl_max_version"], + "ssl-min-version": module.params["sip_ssl_min_version"], + "ssl-mode": module.params["sip_ssl_mode"], + "ssl-pfs": module.params["sip_ssl_pfs"], + "ssl-send-empty-frags": module.params["sip_ssl_send_empty_frags"], + "ssl-server-certificate": module.params["sip_ssl_server_certificate"], + "status": module.params["sip_status"], + "strict-register": module.params["sip_strict_register"], + "subscribe-rate": module.params["sip_subscribe_rate"], + "unknown-header": module.params["sip_unknown_header"], + "update-rate": module.params["sip_update_rate"], + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['sccp', 'sip'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + module.paramgram = paramgram + + results = DEFAULT_RESULT_OBJ + try: + + results = fmgr_voip_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_waf.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_waf.py new file mode 100644 index 00000000..6d7f4040 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_waf.py @@ -0,0 +1,1477 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_waf +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: FortiManager web application firewall security profile +description: + - Manage web application firewall security profiles for FGTs via FMG + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + name: + description: + - WAF Profile name. + required: false + + external: + description: + - Disable/Enable external HTTP Inspection. + - choice | disable | Disable external inspection. + - choice | enable | Enable external inspection. + required: false + choices: ["disable", "enable"] + + extended_log: + description: + - Enable/disable extended logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + comment: + description: + - Comment. + required: false + + address_list: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + address_list_blocked_address: + description: + - Blocked address. + required: false + + address_list_blocked_log: + description: + - Enable/disable logging on blocked addresses. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + address_list_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + address_list_status: + description: + - Status. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + address_list_trusted_address: + description: + - Trusted address. + required: false + + constraint: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + constraint_content_length_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_content_length_length: + description: + - Length of HTTP content in bytes (0 to 2147483647). + required: false + + constraint_content_length_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_content_length_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_content_length_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_address: + description: + - Host address. + required: false + + constraint_exception_content_length: + description: + - HTTP content length in request. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_header_length: + description: + - HTTP header length in request. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_hostname: + description: + - Enable/disable hostname check. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_line_length: + description: + - HTTP line length in request. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_malformed: + description: + - Enable/disable malformed HTTP request check. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_max_cookie: + description: + - Maximum number of cookies in HTTP request. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_max_header_line: + description: + - Maximum number of HTTP header line. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_max_range_segment: + description: + - Maximum number of range segments in HTTP range line. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_max_url_param: + description: + - Maximum number of parameters in URL. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_method: + description: + - Enable/disable HTTP method check. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_param_length: + description: + - Maximum length of parameter in URL, HTTP POST request or HTTP body. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_pattern: + description: + - URL pattern. + required: false + + constraint_exception_regex: + description: + - Enable/disable regular expression based pattern match. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_url_param_length: + description: + - Maximum length of parameter in URL. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_exception_version: + description: + - Enable/disable HTTP version check. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_header_length_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_header_length_length: + description: + - Length of HTTP header in bytes (0 to 2147483647). + required: false + + constraint_header_length_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_header_length_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_header_length_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_hostname_action: + description: + - Action for a hostname constraint. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_hostname_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_hostname_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_hostname_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_line_length_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_line_length_length: + description: + - Length of HTTP line in bytes (0 to 2147483647). + required: false + + constraint_line_length_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_line_length_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_line_length_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_malformed_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_malformed_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_malformed_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_malformed_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_cookie_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_max_cookie_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_cookie_max_cookie: + description: + - Maximum number of cookies in HTTP request (0 to 2147483647). + required: false + + constraint_max_cookie_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_max_cookie_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_header_line_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_max_header_line_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_header_line_max_header_line: + description: + - Maximum number HTTP header lines (0 to 2147483647). + required: false + + constraint_max_header_line_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_max_header_line_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_range_segment_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_max_range_segment_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_range_segment_max_range_segment: + description: + - Maximum number of range segments in HTTP range line (0 to 2147483647). + required: false + + constraint_max_range_segment_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_max_range_segment_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_url_param_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_max_url_param_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_max_url_param_max_url_param: + description: + - Maximum number of parameters in URL (0 to 2147483647). + required: false + + constraint_max_url_param_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_max_url_param_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_method_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_method_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_method_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_method_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_param_length_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_param_length_length: + description: + - Maximum length of parameter in URL, HTTP POST request or HTTP body in bytes (0 to 2147483647). + required: false + + constraint_param_length_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_param_length_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_param_length_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_url_param_length_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_url_param_length_length: + description: + - Maximum length of URL parameter in bytes (0 to 2147483647). + required: false + + constraint_url_param_length_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_url_param_length_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_url_param_length_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_version_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + required: false + choices: ["allow", "block"] + + constraint_version_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + constraint_version_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + constraint_version_status: + description: + - Enable/disable the constraint. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + method: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + method_default_allowed_methods: + description: + - Methods. + - FLAG Based Options. Specify multiple in list form. + - flag | delete | HTTP DELETE method. + - flag | get | HTTP GET method. + - flag | head | HTTP HEAD method. + - flag | options | HTTP OPTIONS method. + - flag | post | HTTP POST method. + - flag | put | HTTP PUT method. + - flag | trace | HTTP TRACE method. + - flag | others | Other HTTP methods. + - flag | connect | HTTP CONNECT method. + required: false + choices: ["delete", "get", "head", "options", "post", "put", "trace", "others", "connect"] + + method_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + method_severity: + description: + - Severity. + - choice | low | low severity + - choice | medium | medium severity + - choice | high | High severity + required: false + choices: ["low", "medium", "high"] + + method_status: + description: + - Status. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + method_method_policy_address: + description: + - Host address. + required: false + + method_method_policy_allowed_methods: + description: + - Allowed Methods. + - FLAG Based Options. Specify multiple in list form. + - flag | delete | HTTP DELETE method. + - flag | get | HTTP GET method. + - flag | head | HTTP HEAD method. + - flag | options | HTTP OPTIONS method. + - flag | post | HTTP POST method. + - flag | put | HTTP PUT method. + - flag | trace | HTTP TRACE method. + - flag | others | Other HTTP methods. + - flag | connect | HTTP CONNECT method. + required: false + choices: ["delete", "get", "head", "options", "post", "put", "trace", "others", "connect"] + + method_method_policy_pattern: + description: + - URL pattern. + required: false + + method_method_policy_regex: + description: + - Enable/disable regular expression based pattern match. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + signature: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + signature_credit_card_detection_threshold: + description: + - The minimum number of Credit cards to detect violation. + required: false + + signature_disabled_signature: + description: + - Disabled signatures + required: false + + signature_disabled_sub_class: + description: + - Disabled signature subclasses. + required: false + + signature_custom_signature_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + - choice | erase | Erase credit card numbers. + required: false + choices: ["allow", "block", "erase"] + + signature_custom_signature_case_sensitivity: + description: + - Case sensitivity in pattern. + - choice | disable | Case insensitive in pattern. + - choice | enable | Case sensitive in pattern. + required: false + choices: ["disable", "enable"] + + signature_custom_signature_direction: + description: + - Traffic direction. + - choice | request | Match HTTP request. + - choice | response | Match HTTP response. + required: false + choices: ["request", "response"] + + signature_custom_signature_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + signature_custom_signature_name: + description: + - Signature name. + required: false + + signature_custom_signature_pattern: + description: + - Match pattern. + required: false + + signature_custom_signature_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + signature_custom_signature_status: + description: + - Status. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + signature_custom_signature_target: + description: + - Match HTTP target. + - FLAG Based Options. Specify multiple in list form. + - flag | arg | HTTP arguments. + - flag | arg-name | Names of HTTP arguments. + - flag | req-body | HTTP request body. + - flag | req-cookie | HTTP request cookies. + - flag | req-cookie-name | HTTP request cookie names. + - flag | req-filename | HTTP request file name. + - flag | req-header | HTTP request headers. + - flag | req-header-name | HTTP request header names. + - flag | req-raw-uri | Raw URI of HTTP request. + - flag | req-uri | URI of HTTP request. + - flag | resp-body | HTTP response body. + - flag | resp-hdr | HTTP response headers. + - flag | resp-status | HTTP response status. + required: false + choices: ["arg","arg-name","req-body","req-cookie","req-cookie-name","req-filename","req-header","req-header-name", + "req-raw-uri","req-uri","resp-body","resp-hdr","resp-status"] + + signature_main_class_action: + description: + - Action. + - choice | allow | Allow. + - choice | block | Block. + - choice | erase | Erase credit card numbers. + required: false + choices: ["allow", "block", "erase"] + + signature_main_class_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + signature_main_class_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + signature_main_class_status: + description: + - Status. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + url_access: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + url_access_action: + description: + - Action. + - choice | bypass | Allow the HTTP request, also bypass further WAF scanning. + - choice | permit | Allow the HTTP request, and continue further WAF scanning. + - choice | block | Block HTTP request. + required: false + choices: ["bypass", "permit", "block"] + + url_access_address: + description: + - Host address. + required: false + + url_access_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + url_access_severity: + description: + - Severity. + - choice | low | Low severity. + - choice | medium | Medium severity. + - choice | high | High severity. + required: false + choices: ["low", "medium", "high"] + + url_access_access_pattern_negate: + description: + - Enable/disable match negation. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + url_access_access_pattern_pattern: + description: + - URL pattern. + required: false + + url_access_access_pattern_regex: + description: + - Enable/disable regular expression based pattern match. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + url_access_access_pattern_srcaddr: + description: + - Source address. + required: false + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_waf: + name: "Ansible_WAF_Profile" + comment: "Created by Ansible Module TEST" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_waf: + name: "Ansible_WAF_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_waf_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + mode = paramgram["mode"] + adom = paramgram["adom"] + # INIT A BASIC OBJECTS + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/waf/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/waf/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + name=dict(required=False, type="str"), + external=dict(required=False, type="str", choices=["disable", "enable"]), + extended_log=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + address_list=dict(required=False, type="list"), + address_list_blocked_address=dict(required=False, type="str"), + address_list_blocked_log=dict(required=False, type="str", choices=["disable", "enable"]), + address_list_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + address_list_status=dict(required=False, type="str", choices=["disable", "enable"]), + address_list_trusted_address=dict(required=False, type="str"), + constraint=dict(required=False, type="list"), + + constraint_content_length_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_content_length_length=dict(required=False, type="int"), + constraint_content_length_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_content_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_content_length_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_exception_address=dict(required=False, type="str"), + constraint_exception_content_length=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_header_length=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_hostname=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_line_length=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_malformed=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_max_cookie=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_max_header_line=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_max_range_segment=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_max_url_param=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_method=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_param_length=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_pattern=dict(required=False, type="str"), + constraint_exception_regex=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_url_param_length=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_exception_version=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_header_length_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_header_length_length=dict(required=False, type="int"), + constraint_header_length_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_header_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_header_length_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_hostname_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_hostname_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_hostname_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_hostname_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_line_length_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_line_length_length=dict(required=False, type="int"), + constraint_line_length_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_line_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_line_length_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_malformed_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_malformed_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_malformed_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_malformed_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_max_cookie_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_max_cookie_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_max_cookie_max_cookie=dict(required=False, type="int"), + constraint_max_cookie_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_max_cookie_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_max_header_line_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_max_header_line_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_max_header_line_max_header_line=dict(required=False, type="int"), + constraint_max_header_line_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_max_header_line_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_max_range_segment_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_max_range_segment_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_max_range_segment_max_range_segment=dict(required=False, type="int"), + constraint_max_range_segment_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_max_range_segment_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_max_url_param_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_max_url_param_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_max_url_param_max_url_param=dict(required=False, type="int"), + constraint_max_url_param_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_max_url_param_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_method_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_method_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_method_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_method_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_param_length_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_param_length_length=dict(required=False, type="int"), + constraint_param_length_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_param_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_param_length_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_url_param_length_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_url_param_length_length=dict(required=False, type="int"), + constraint_url_param_length_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_url_param_length_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_url_param_length_status=dict(required=False, type="str", choices=["disable", "enable"]), + + constraint_version_action=dict(required=False, type="str", choices=["allow", "block"]), + constraint_version_log=dict(required=False, type="str", choices=["disable", "enable"]), + constraint_version_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + constraint_version_status=dict(required=False, type="str", choices=["disable", "enable"]), + method=dict(required=False, type="list"), + method_default_allowed_methods=dict(required=False, type="str", choices=["delete", + "get", + "head", + "options", + "post", + "put", + "trace", + "others", + "connect"]), + method_log=dict(required=False, type="str", choices=["disable", "enable"]), + method_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + method_status=dict(required=False, type="str", choices=["disable", "enable"]), + + method_method_policy_address=dict(required=False, type="str"), + method_method_policy_allowed_methods=dict(required=False, type="str", choices=["delete", + "get", + "head", + "options", + "post", + "put", + "trace", + "others", + "connect"]), + method_method_policy_pattern=dict(required=False, type="str"), + method_method_policy_regex=dict(required=False, type="str", choices=["disable", "enable"]), + signature=dict(required=False, type="list"), + signature_credit_card_detection_threshold=dict(required=False, type="int"), + signature_disabled_signature=dict(required=False, type="str"), + signature_disabled_sub_class=dict(required=False, type="str"), + + signature_custom_signature_action=dict(required=False, type="str", choices=["allow", "block", "erase"]), + signature_custom_signature_case_sensitivity=dict(required=False, type="str", choices=["disable", "enable"]), + signature_custom_signature_direction=dict(required=False, type="str", choices=["request", "response"]), + signature_custom_signature_log=dict(required=False, type="str", choices=["disable", "enable"]), + signature_custom_signature_name=dict(required=False, type="str"), + signature_custom_signature_pattern=dict(required=False, type="str"), + signature_custom_signature_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + signature_custom_signature_status=dict(required=False, type="str", choices=["disable", "enable"]), + signature_custom_signature_target=dict(required=False, type="str", choices=["arg", + "arg-name", + "req-body", + "req-cookie", + "req-cookie-name", + "req-filename", + "req-header", + "req-header-name", + "req-raw-uri", + "req-uri", + "resp-body", + "resp-hdr", + "resp-status"]), + + signature_main_class_action=dict(required=False, type="str", choices=["allow", "block", "erase"]), + signature_main_class_log=dict(required=False, type="str", choices=["disable", "enable"]), + signature_main_class_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + signature_main_class_status=dict(required=False, type="str", choices=["disable", "enable"]), + url_access=dict(required=False, type="list"), + url_access_action=dict(required=False, type="str", choices=["bypass", "permit", "block"]), + url_access_address=dict(required=False, type="str"), + url_access_log=dict(required=False, type="str", choices=["disable", "enable"]), + url_access_severity=dict(required=False, type="str", choices=["low", "medium", "high"]), + + url_access_access_pattern_negate=dict(required=False, type="str", choices=["disable", "enable"]), + url_access_access_pattern_pattern=dict(required=False, type="str"), + url_access_access_pattern_regex=dict(required=False, type="str", choices=["disable", "enable"]), + url_access_access_pattern_srcaddr=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "name": module.params["name"], + "external": module.params["external"], + "extended-log": module.params["extended_log"], + "comment": module.params["comment"], + "address-list": { + "blocked-address": module.params["address_list_blocked_address"], + "blocked-log": module.params["address_list_blocked_log"], + "severity": module.params["address_list_severity"], + "status": module.params["address_list_status"], + "trusted-address": module.params["address_list_trusted_address"], + }, + "constraint": { + "content-length": { + "action": module.params["constraint_content_length_action"], + "length": module.params["constraint_content_length_length"], + "log": module.params["constraint_content_length_log"], + "severity": module.params["constraint_content_length_severity"], + "status": module.params["constraint_content_length_status"], + }, + "exception": { + "address": module.params["constraint_exception_address"], + "content-length": module.params["constraint_exception_content_length"], + "header-length": module.params["constraint_exception_header_length"], + "hostname": module.params["constraint_exception_hostname"], + "line-length": module.params["constraint_exception_line_length"], + "malformed": module.params["constraint_exception_malformed"], + "max-cookie": module.params["constraint_exception_max_cookie"], + "max-header-line": module.params["constraint_exception_max_header_line"], + "max-range-segment": module.params["constraint_exception_max_range_segment"], + "max-url-param": module.params["constraint_exception_max_url_param"], + "method": module.params["constraint_exception_method"], + "param-length": module.params["constraint_exception_param_length"], + "pattern": module.params["constraint_exception_pattern"], + "regex": module.params["constraint_exception_regex"], + "url-param-length": module.params["constraint_exception_url_param_length"], + "version": module.params["constraint_exception_version"], + }, + "header-length": { + "action": module.params["constraint_header_length_action"], + "length": module.params["constraint_header_length_length"], + "log": module.params["constraint_header_length_log"], + "severity": module.params["constraint_header_length_severity"], + "status": module.params["constraint_header_length_status"], + }, + "hostname": { + "action": module.params["constraint_hostname_action"], + "log": module.params["constraint_hostname_log"], + "severity": module.params["constraint_hostname_severity"], + "status": module.params["constraint_hostname_status"], + }, + "line-length": { + "action": module.params["constraint_line_length_action"], + "length": module.params["constraint_line_length_length"], + "log": module.params["constraint_line_length_log"], + "severity": module.params["constraint_line_length_severity"], + "status": module.params["constraint_line_length_status"], + }, + "malformed": { + "action": module.params["constraint_malformed_action"], + "log": module.params["constraint_malformed_log"], + "severity": module.params["constraint_malformed_severity"], + "status": module.params["constraint_malformed_status"], + }, + "max-cookie": { + "action": module.params["constraint_max_cookie_action"], + "log": module.params["constraint_max_cookie_log"], + "max-cookie": module.params["constraint_max_cookie_max_cookie"], + "severity": module.params["constraint_max_cookie_severity"], + "status": module.params["constraint_max_cookie_status"], + }, + "max-header-line": { + "action": module.params["constraint_max_header_line_action"], + "log": module.params["constraint_max_header_line_log"], + "max-header-line": module.params["constraint_max_header_line_max_header_line"], + "severity": module.params["constraint_max_header_line_severity"], + "status": module.params["constraint_max_header_line_status"], + }, + "max-range-segment": { + "action": module.params["constraint_max_range_segment_action"], + "log": module.params["constraint_max_range_segment_log"], + "max-range-segment": module.params["constraint_max_range_segment_max_range_segment"], + "severity": module.params["constraint_max_range_segment_severity"], + "status": module.params["constraint_max_range_segment_status"], + }, + "max-url-param": { + "action": module.params["constraint_max_url_param_action"], + "log": module.params["constraint_max_url_param_log"], + "max-url-param": module.params["constraint_max_url_param_max_url_param"], + "severity": module.params["constraint_max_url_param_severity"], + "status": module.params["constraint_max_url_param_status"], + }, + "method": { + "action": module.params["constraint_method_action"], + "log": module.params["constraint_method_log"], + "severity": module.params["constraint_method_severity"], + "status": module.params["constraint_method_status"], + }, + "param-length": { + "action": module.params["constraint_param_length_action"], + "length": module.params["constraint_param_length_length"], + "log": module.params["constraint_param_length_log"], + "severity": module.params["constraint_param_length_severity"], + "status": module.params["constraint_param_length_status"], + }, + "url-param-length": { + "action": module.params["constraint_url_param_length_action"], + "length": module.params["constraint_url_param_length_length"], + "log": module.params["constraint_url_param_length_log"], + "severity": module.params["constraint_url_param_length_severity"], + "status": module.params["constraint_url_param_length_status"], + }, + "version": { + "action": module.params["constraint_version_action"], + "log": module.params["constraint_version_log"], + "severity": module.params["constraint_version_severity"], + "status": module.params["constraint_version_status"], + }, + }, + "method": { + "default-allowed-methods": module.params["method_default_allowed_methods"], + "log": module.params["method_log"], + "severity": module.params["method_severity"], + "status": module.params["method_status"], + "method-policy": { + "address": module.params["method_method_policy_address"], + "allowed-methods": module.params["method_method_policy_allowed_methods"], + "pattern": module.params["method_method_policy_pattern"], + "regex": module.params["method_method_policy_regex"], + }, + }, + "signature": { + "credit-card-detection-threshold": module.params["signature_credit_card_detection_threshold"], + "disabled-signature": module.params["signature_disabled_signature"], + "disabled-sub-class": module.params["signature_disabled_sub_class"], + "custom-signature": { + "action": module.params["signature_custom_signature_action"], + "case-sensitivity": module.params["signature_custom_signature_case_sensitivity"], + "direction": module.params["signature_custom_signature_direction"], + "log": module.params["signature_custom_signature_log"], + "name": module.params["signature_custom_signature_name"], + "pattern": module.params["signature_custom_signature_pattern"], + "severity": module.params["signature_custom_signature_severity"], + "status": module.params["signature_custom_signature_status"], + "target": module.params["signature_custom_signature_target"], + }, + "main-class": { + "action": module.params["signature_main_class_action"], + "log": module.params["signature_main_class_log"], + "severity": module.params["signature_main_class_severity"], + "status": module.params["signature_main_class_status"], + }, + }, + "url-access": { + "action": module.params["url_access_action"], + "address": module.params["url_access_address"], + "log": module.params["url_access_log"], + "severity": module.params["url_access_severity"], + "access-pattern": { + "negate": module.params["url_access_access_pattern_negate"], + "pattern": module.params["url_access_access_pattern_pattern"], + "regex": module.params["url_access_access_pattern_regex"], + "srcaddr": module.params["url_access_access_pattern_srcaddr"], + } + } + } + + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['address-list', 'constraint', 'method', 'signature', 'url-access'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + + try: + results = fmgr_waf_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_wanopt.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_wanopt.py new file mode 100644 index 00000000..68f0962b --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_wanopt.py @@ -0,0 +1,685 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_wanopt +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: WAN optimization +description: + - Manage WanOpt security profiles in FortiManager via API + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + transparent: + description: + - Enable/disable transparent mode. + required: false + choices: + - disable + - enable + + name: + description: + - Profile name. + required: false + + comments: + description: + - Comment. + required: false + + auth_group: + description: + - Optionally add an authentication group to restrict access to the WAN Optimization tunnel to + peers in the authentication group. + required: false + + cifs: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + cifs_byte_caching: + description: + - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching + file data sent across the WAN and in future serving if from the cache. + required: false + choices: + - disable + - enable + + cifs_log_traffic: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + cifs_port: + description: + - Single port number or port number range for CIFS. Only packets with a destination port number + that matches this port number or range are accepted by this profile. + required: false + + cifs_prefer_chunking: + description: + - Select dynamic or fixed-size data chunking for HTTP WAN Optimization. + required: false + choices: + - dynamic + - fix + + cifs_secure_tunnel: + description: + - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the + same TCP port (7810). + required: false + choices: + - disable + - enable + + cifs_status: + description: + - Enable/disable HTTP WAN Optimization. + required: false + choices: + - disable + - enable + + cifs_tunnel_sharing: + description: + - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols. + required: false + choices: + - private + - shared + - express-shared + + ftp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ftp_byte_caching: + description: + - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching + file data sent across the WAN and in future serving if from the cache. + required: false + choices: + - disable + - enable + + ftp_log_traffic: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + ftp_port: + description: + - Single port number or port number range for FTP. Only packets with a destination port number + that matches this port number or range are accepted by this profile. + required: false + + ftp_prefer_chunking: + description: + - Select dynamic or fixed-size data chunking for HTTP WAN Optimization. + required: false + choices: + - dynamic + - fix + + ftp_secure_tunnel: + description: + - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the + same TCP port (7810). + required: false + choices: + - disable + - enable + + ftp_status: + description: + - Enable/disable HTTP WAN Optimization. + required: false + choices: + - disable + - enable + + ftp_tunnel_sharing: + description: + - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols. + required: false + choices: + - private + - shared + - express-shared + + http: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + http_byte_caching: + description: + - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching + file data sent across the WAN and in future serving if from the cache. + required: false + choices: + - disable + - enable + + http_log_traffic: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + http_port: + description: + - Single port number or port number range for HTTP. Only packets with a destination port number + that matches this port number or range are accepted by this profile. + required: false + + http_prefer_chunking: + description: + - Select dynamic or fixed-size data chunking for HTTP WAN Optimization. + required: false + choices: + - dynamic + - fix + + http_secure_tunnel: + description: + - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the + same TCP port (7810). + required: false + choices: + - disable + - enable + + http_ssl: + description: + - Enable/disable SSL/TLS offloading (hardware acceleration) for HTTPS traffic in this tunnel. + required: false + choices: + - disable + - enable + + http_ssl_port: + description: + - Port on which to expect HTTPS traffic for SSL/TLS offloading. + required: false + + http_status: + description: + - Enable/disable HTTP WAN Optimization. + required: false + choices: + - disable + - enable + + http_tunnel_non_http: + description: + - Configure how to process non-HTTP traffic when a profile configured for HTTP traffic accepts + a non-HTTP session. Can occur if an application sends non-HTTP traffic using an HTTP destination port. + required: false + choices: + - disable + - enable + + http_tunnel_sharing: + description: + - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols. + required: false + choices: + - private + - shared + - express-shared + + http_unknown_http_version: + description: + - How to handle HTTP sessions that do not comply with HTTP 0.9, 1.0, or 1.1. + required: false + choices: + - best-effort + - reject + - tunnel + + mapi: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + mapi_byte_caching: + description: + - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching + file data sent across the WAN and in future serving if from the cache. + required: false + choices: + - disable + - enable + + mapi_log_traffic: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + mapi_port: + description: + - Single port number or port number range for MAPI. Only packets with a destination port number + that matches this port number or range are accepted by this profile. + required: false + + mapi_secure_tunnel: + description: + - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the + same TCP port (7810). + required: false + choices: + - disable + - enable + + mapi_status: + description: + - Enable/disable HTTP WAN Optimization. + required: false + choices: + - disable + - enable + + mapi_tunnel_sharing: + description: + - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols. + required: false + choices: + - private + - shared + - express-shared + + tcp: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + tcp_byte_caching: + description: + - Enable/disable byte-caching for HTTP. Byte caching reduces the amount of traffic by caching + file data sent across the WAN and in future serving if from the cache. + required: false + choices: + - disable + - enable + + tcp_byte_caching_opt: + description: + - Select whether TCP byte-caching uses system memory only or both memory and disk space. + required: false + choices: + - mem-only + - mem-disk + + tcp_log_traffic: + description: + - Enable/disable logging. + required: false + choices: + - disable + - enable + + tcp_port: + description: + - Single port number or port number range for TCP. Only packets with a destination port number + that matches this port number or range are accepted by this profile. + required: false + + tcp_secure_tunnel: + description: + - Enable/disable securing the WAN Opt tunnel using SSL. Secure and non-secure tunnels use the + same TCP port (7810). + required: false + choices: + - disable + - enable + + tcp_ssl: + description: + - Enable/disable SSL/TLS offloading. + required: false + choices: + - disable + - enable + + tcp_ssl_port: + description: + - Port on which to expect HTTPS traffic for SSL/TLS offloading. + required: false + + tcp_status: + description: + - Enable/disable HTTP WAN Optimization. + required: false + choices: + - disable + - enable + + tcp_tunnel_sharing: + description: + - Tunnel sharing mode for aggressive/non-aggressive and/or interactive/non-interactive protocols. + required: false + choices: + - private + - shared + - express-shared + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_wanopt: + name: "Ansible_WanOpt_Profile" + mode: "delete" + + - name: Create FMGR_WANOPT_PROFILE + community.fortios.fmgr_secprof_wanopt: + mode: "set" + adom: "root" + transparent: "enable" + name: "Ansible_WanOpt_Profile" + comments: "Created by Ansible" + cifs: {byte-caching: "enable", + log-traffic: "enable", + port: 80, + prefer-chunking: "dynamic", + status: "enable", + tunnel-sharing: "private"} + ftp: {byte-caching: "enable", + log-traffic: "enable", + port: 80, + prefer-chunking: "dynamic", + secure-tunnel: "disable", + status: "enable", + tunnel-sharing: "private"} +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +############### +# START METHODS +############### + + +def fmgr_wanopt_profile_modify(fmgr, paramgram): + """ + :param fmgr: The fmgr object instance from fortimanager.py + :type fmgr: class object + :param paramgram: The formatted dictionary of options to process + :type paramgram: dict + :return: The response from the FortiManager + :rtype: dict + """ + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/wanopt/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/wanopt/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + transparent=dict(required=False, type="str", choices=["disable", "enable"]), + name=dict(required=False, type="str"), + comments=dict(required=False, type="str"), + auth_group=dict(required=False, type="str"), + cifs=dict(required=False, type="dict"), + cifs_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]), + cifs_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]), + cifs_port=dict(required=False, type="str"), + cifs_prefer_chunking=dict(required=False, type="str", choices=["dynamic", "fix"]), + cifs_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]), + cifs_status=dict(required=False, type="str", choices=["disable", "enable"]), + cifs_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]), + ftp=dict(required=False, type="dict"), + ftp_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]), + ftp_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]), + ftp_port=dict(required=False, type="str"), + ftp_prefer_chunking=dict(required=False, type="str", choices=["dynamic", "fix"]), + ftp_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]), + ftp_status=dict(required=False, type="str", choices=["disable", "enable"]), + ftp_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]), + http=dict(required=False, type="dict"), + http_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]), + http_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]), + http_port=dict(required=False, type="str"), + http_prefer_chunking=dict(required=False, type="str", choices=["dynamic", "fix"]), + http_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]), + http_ssl=dict(required=False, type="str", choices=["disable", "enable"]), + http_ssl_port=dict(required=False, type="str"), + http_status=dict(required=False, type="str", choices=["disable", "enable"]), + http_tunnel_non_http=dict(required=False, type="str", choices=["disable", "enable"]), + http_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]), + http_unknown_http_version=dict(required=False, type="str", choices=["best-effort", "reject", "tunnel"]), + mapi=dict(required=False, type="dict"), + mapi_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]), + mapi_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]), + mapi_port=dict(required=False, type="str"), + mapi_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]), + mapi_status=dict(required=False, type="str", choices=["disable", "enable"]), + mapi_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]), + tcp=dict(required=False, type="dict"), + tcp_byte_caching=dict(required=False, type="str", choices=["disable", "enable"]), + tcp_byte_caching_opt=dict(required=False, type="str", choices=["mem-only", "mem-disk"]), + tcp_log_traffic=dict(required=False, type="str", choices=["disable", "enable"]), + tcp_port=dict(required=False, type="str"), + tcp_secure_tunnel=dict(required=False, type="str", choices=["disable", "enable"]), + tcp_ssl=dict(required=False, type="str", choices=["disable", "enable"]), + tcp_ssl_port=dict(required=False, type="str"), + tcp_status=dict(required=False, type="str", choices=["disable", "enable"]), + tcp_tunnel_sharing=dict(required=False, type="str", choices=["private", "shared", "express-shared"]), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "transparent": module.params["transparent"], + "name": module.params["name"], + "comments": module.params["comments"], + "auth-group": module.params["auth_group"], + "cifs": { + "byte-caching": module.params["cifs_byte_caching"], + "log-traffic": module.params["cifs_log_traffic"], + "port": module.params["cifs_port"], + "prefer-chunking": module.params["cifs_prefer_chunking"], + "secure-tunnel": module.params["cifs_secure_tunnel"], + "status": module.params["cifs_status"], + "tunnel-sharing": module.params["cifs_tunnel_sharing"], + }, + "ftp": { + "byte-caching": module.params["ftp_byte_caching"], + "log-traffic": module.params["ftp_log_traffic"], + "port": module.params["ftp_port"], + "prefer-chunking": module.params["ftp_prefer_chunking"], + "secure-tunnel": module.params["ftp_secure_tunnel"], + "status": module.params["ftp_status"], + "tunnel-sharing": module.params["ftp_tunnel_sharing"], + }, + "http": { + "byte-caching": module.params["http_byte_caching"], + "log-traffic": module.params["http_log_traffic"], + "port": module.params["http_port"], + "prefer-chunking": module.params["http_prefer_chunking"], + "secure-tunnel": module.params["http_secure_tunnel"], + "ssl": module.params["http_ssl"], + "ssl-port": module.params["http_ssl_port"], + "status": module.params["http_status"], + "tunnel-non-http": module.params["http_tunnel_non_http"], + "tunnel-sharing": module.params["http_tunnel_sharing"], + "unknown-http-version": module.params["http_unknown_http_version"], + }, + "mapi": { + "byte-caching": module.params["mapi_byte_caching"], + "log-traffic": module.params["mapi_log_traffic"], + "port": module.params["mapi_port"], + "secure-tunnel": module.params["mapi_secure_tunnel"], + "status": module.params["mapi_status"], + "tunnel-sharing": module.params["mapi_tunnel_sharing"], + }, + "tcp": { + "byte-caching": module.params["tcp_byte_caching"], + "byte-caching-opt": module.params["tcp_byte_caching_opt"], + "log-traffic": module.params["tcp_log_traffic"], + "port": module.params["tcp_port"], + "secure-tunnel": module.params["tcp_secure_tunnel"], + "ssl": module.params["tcp_ssl"], + "ssl-port": module.params["tcp_ssl_port"], + "status": module.params["tcp_status"], + "tunnel-sharing": module.params["tcp_tunnel_sharing"], + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['cifs', 'ftp', 'http', 'mapi', 'tcp'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + + try: + results = fmgr_wanopt_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() diff --git a/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_web.py b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_web.py new file mode 100644 index 00000000..427cd2e0 --- /dev/null +++ b/collections-debian-merged/ansible_collections/community/fortios/plugins/modules/fmgr_secprof_web.py @@ -0,0 +1,1081 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible 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. +# +# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>. +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_web +notes: + - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage web filter security profiles in FortiManager +description: + - Manage web filter security profiles in FortiManager through playbooks using the FMG API + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + youtube_channel_status: + description: + - YouTube channel filter status. + - choice | disable | Disable YouTube channel filter. + - choice | blacklist | Block matches. + - choice | whitelist | Allow matches. + required: false + choices: ["disable", "blacklist", "whitelist"] + + wisp_servers: + description: + - WISP servers. + required: false + + wisp_algorithm: + description: + - WISP server selection algorithm. + - choice | auto-learning | Select the lightest loading healthy server. + - choice | primary-secondary | Select the first healthy server in order. + - choice | round-robin | Select the next healthy server. + required: false + choices: ["auto-learning", "primary-secondary", "round-robin"] + + wisp: + description: + - Enable/disable web proxy WISP. + - choice | disable | Disable web proxy WISP. + - choice | enable | Enable web proxy WISP. + required: false + choices: ["disable", "enable"] + + web_url_log: + description: + - Enable/disable logging URL filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_invalid_domain_log: + description: + - Enable/disable logging invalid domain names. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_ftgd_quota_usage: + description: + - Enable/disable logging daily quota usage. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_ftgd_err_log: + description: + - Enable/disable logging rating errors. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_vbs_log: + description: + - Enable/disable logging VBS scripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_unknown_log: + description: + - Enable/disable logging unknown scripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_referer_log: + description: + - Enable/disable logging referrers. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_jscript_log: + description: + - Enable/disable logging JScripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_js_log: + description: + - Enable/disable logging Java scripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_cookie_removal_log: + description: + - Enable/disable logging blocked cookies. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_cookie_log: + description: + - Enable/disable logging cookie filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_command_block_log: + description: + - Enable/disable logging blocked commands. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_applet_log: + description: + - Enable/disable logging Java applets. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_activex_log: + description: + - Enable/disable logging ActiveX. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_extended_all_action_log: + description: + - Enable/disable extended any filter action logging for web filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_content_log: + description: + - Enable/disable logging logging blocked web content. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + replacemsg_group: + description: + - Replacement message group. + required: false + + post_action: + description: + - Action taken for HTTP POST traffic. + - choice | normal | Normal, POST requests are allowed. + - choice | block | POST requests are blocked. + required: false + choices: ["normal", "block"] + + ovrd_perm: + description: + - FLAG Based Options. Specify multiple in list form. + - flag | bannedword-override | Banned word override. + - flag | urlfilter-override | URL filter override. + - flag | fortiguard-wf-override | FortiGuard Web Filter override. + - flag | contenttype-check-override | Content-type header override. + required: false + choices: + - bannedword-override + - urlfilter-override + - fortiguard-wf-override + - contenttype-check-override + + options: + description: + - FLAG Based Options. Specify multiple in list form. + - flag | block-invalid-url | Block sessions contained an invalid domain name. + - flag | jscript | Javascript block. + - flag | js | JS block. + - flag | vbs | VB script block. + - flag | unknown | Unknown script block. + - flag | wf-referer | Referring block. + - flag | intrinsic | Intrinsic script block. + - flag | wf-cookie | Cookie block. + - flag | per-user-bwl | Per-user black/white list filter + - flag | activexfilter | ActiveX filter. + - flag | cookiefilter | Cookie filter. + - flag | javafilter | Java applet filter. + required: false + choices: + - block-invalid-url + - jscript + - js + - vbs + - unknown + - wf-referer + - intrinsic + - wf-cookie + - per-user-bwl + - activexfilter + - cookiefilter + - javafilter + + name: + description: + - Profile name. + required: false + + log_all_url: + description: + - Enable/disable logging all URLs visited. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + inspection_mode: + description: + - Web filtering inspection mode. + - choice | proxy | Proxy. + - choice | flow-based | Flow based. + required: false + choices: ["proxy", "flow-based"] + + https_replacemsg: + description: + - Enable replacement messages for HTTPS. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + extended_log: + description: + - Enable/disable extended logging for web filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + comment: + description: + - Optional comments. + required: false + + ftgd_wf: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ftgd_wf_exempt_quota: + description: + - Do not stop quota for these categories. + required: false + + ftgd_wf_max_quota_timeout: + description: + - Maximum FortiGuard quota used by single page view in seconds (excludes streams). + required: false + + ftgd_wf_options: + description: + - Options for FortiGuard Web Filter. + - FLAG Based Options. Specify multiple in list form. + - flag | error-allow | Allow web pages with a rating error to pass through. + - flag | rate-server-ip | Rate the server IP in addition to the domain name. + - flag | connect-request-bypass | Bypass connection which has CONNECT request. + - flag | ftgd-disable | Disable FortiGuard scanning. + required: false + choices: ["error-allow", "rate-server-ip", "connect-request-bypass", "ftgd-disable"] + + ftgd_wf_ovrd: + description: + - Allow web filter profile overrides. + required: false + + ftgd_wf_rate_crl_urls: + description: + - Enable/disable rating CRL by URL. + - choice | disable | Disable rating CRL by URL. + - choice | enable | Enable rating CRL by URL. + required: false + choices: ["disable", "enable"] + + ftgd_wf_rate_css_urls: + description: + - Enable/disable rating CSS by URL. + - choice | disable | Disable rating CSS by URL. + - choice | enable | Enable rating CSS by URL. + required: false + choices: ["disable", "enable"] + + ftgd_wf_rate_image_urls: + description: + - Enable/disable rating images by URL. + - choice | disable | Disable rating images by URL (blocked images are replaced with blanks). + - choice | enable | Enable rating images by URL (blocked images are replaced with blanks). + required: false + choices: ["disable", "enable"] + + ftgd_wf_rate_javascript_urls: + description: + - Enable/disable rating JavaScript by URL. + - choice | disable | Disable rating JavaScript by URL. + - choice | enable | Enable rating JavaScript by URL. + required: false + choices: ["disable", "enable"] + + ftgd_wf_filters_action: + description: + - Action to take for matches. + - choice | block | Block access. + - choice | monitor | Allow access while logging the action. + - choice | warning | Allow access after warning the user. + - choice | authenticate | Authenticate user before allowing access. + required: false + choices: ["block", "monitor", "warning", "authenticate"] + + ftgd_wf_filters_auth_usr_grp: + description: + - Groups with permission to authenticate. + required: false + + ftgd_wf_filters_category: + description: + - Categories and groups the filter examines. + required: false + + ftgd_wf_filters_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ftgd_wf_filters_override_replacemsg: + description: + - Override replacement message. + required: false + + ftgd_wf_filters_warn_duration: + description: + - Duration of warnings. + required: false + + ftgd_wf_filters_warning_duration_type: + description: + - Re-display warning after closing browser or after a timeout. + - choice | session | After session ends. + - choice | timeout | After timeout occurs. + required: false + choices: ["session", "timeout"] + + ftgd_wf_filters_warning_prompt: + description: + - Warning prompts in each category or each domain. + - choice | per-domain | Per-domain warnings. + - choice | per-category | Per-category warnings. + required: false + choices: ["per-domain", "per-category"] + + ftgd_wf_quota_category: + description: + - FortiGuard categories to apply quota to (category action must be set to monitor). + required: false + + ftgd_wf_quota_duration: + description: + - Duration of quota. + required: false + + ftgd_wf_quota_override_replacemsg: + description: + - Override replacement message. + required: false + + ftgd_wf_quota_type: + description: + - Quota type. + - choice | time | Use a time-based quota. + - choice | traffic | Use a traffic-based quota. + required: false + choices: ["time", "traffic"] + + ftgd_wf_quota_unit: + description: + - Traffic quota unit of measurement. + - choice | B | Quota in bytes. + - choice | KB | Quota in kilobytes. + - choice | MB | Quota in megabytes. + - choice | GB | Quota in gigabytes. + required: false + choices: ["B", "KB", "MB", "GB"] + + ftgd_wf_quota_value: + description: + - Traffic quota value. + required: false + + override: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + override_ovrd_cookie: + description: + - Allow/deny browser-based (cookie) overrides. + - choice | deny | Deny browser-based (cookie) override. + - choice | allow | Allow browser-based (cookie) override. + required: false + choices: ["deny", "allow"] + + override_ovrd_dur: + description: + - Override duration. + required: false + + override_ovrd_dur_mode: + description: + - Override duration mode. + - choice | constant | Constant mode. + - choice | ask | Prompt for duration when initiating an override. + required: false + choices: ["constant", "ask"] + + override_ovrd_scope: + description: + - Override scope. + - choice | user | Override for the user. + - choice | user-group | Override for the user's group. + - choice | ip | Override for the initiating IP. + - choice | ask | Prompt for scope when initiating an override. + - choice | browser | Create browser-based (cookie) override. + required: false + choices: ["user", "user-group", "ip", "ask", "browser"] + + override_ovrd_user_group: + description: + - User groups with permission to use the override. + required: false + + override_profile: + description: + - Web filter profile with permission to create overrides. + required: false + + override_profile_attribute: + description: + - Profile attribute to retrieve from the RADIUS server. + - choice | User-Name | Use this attribute. + - choice | NAS-IP-Address | Use this attribute. + - choice | Framed-IP-Address | Use this attribute. + - choice | Framed-IP-Netmask | Use this attribute. + - choice | Filter-Id | Use this attribute. + - choice | Login-IP-Host | Use this attribute. + - choice | Reply-Message | Use this attribute. + - choice | Callback-Number | Use this attribute. + - choice | Callback-Id | Use this attribute. + - choice | Framed-Route | Use this attribute. + - choice | Framed-IPX-Network | Use this attribute. + - choice | Class | Use this attribute. + - choice | Called-Station-Id | Use this attribute. + - choice | Calling-Station-Id | Use this attribute. + - choice | NAS-Identifier | Use this attribute. + - choice | Proxy-State | Use this attribute. + - choice | Login-LAT-Service | Use this attribute. + - choice | Login-LAT-Node | Use this attribute. + - choice | Login-LAT-Group | Use this attribute. + - choice | Framed-AppleTalk-Zone | Use this attribute. + - choice | Acct-Session-Id | Use this attribute. + - choice | Acct-Multi-Session-Id | Use this attribute. + required: false + choices: + - User-Name + - NAS-IP-Address + - Framed-IP-Address + - Framed-IP-Netmask + - Filter-Id + - Login-IP-Host + - Reply-Message + - Callback-Number + - Callback-Id + - Framed-Route + - Framed-IPX-Network + - Class + - Called-Station-Id + - Calling-Station-Id + - NAS-Identifier + - Proxy-State + - Login-LAT-Service + - Login-LAT-Node + - Login-LAT-Group + - Framed-AppleTalk-Zone + - Acct-Session-Id + - Acct-Multi-Session-Id + + override_profile_type: + description: + - Override profile type. + - choice | list | Profile chosen from list. + - choice | radius | Profile determined by RADIUS server. + required: false + choices: ["list", "radius"] + + url_extraction: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + url_extraction_redirect_header: + description: + - HTTP header name to use for client redirect on blocked requests + required: false + + url_extraction_redirect_no_content: + description: + - Enable / Disable empty message-body entity in HTTP response + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + url_extraction_redirect_url: + description: + - HTTP header value to use for client redirect on blocked requests + required: false + + url_extraction_server_fqdn: + description: + - URL extraction server FQDN (fully qualified domain name) + required: false + + url_extraction_status: + description: + - Enable URL Extraction + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + web_blacklist: + description: + - Enable/disable automatic addition of URLs detected by FortiSandbox to blacklist. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_bword_table: + description: + - Banned word table ID. + required: false + + web_bword_threshold: + description: + - Banned word score threshold. + required: false + + web_content_header_list: + description: + - Content header list. + required: false + + web_keyword_match: + description: + - Search keywords to log when match is found. + required: false + + web_log_search: + description: + - Enable/disable logging all search phrases. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_safe_search: + description: + - Safe search type. + - FLAG Based Options. Specify multiple in list form. + - flag | url | Insert safe search string into URL. + - flag | header | Insert safe search header. + required: false + choices: ["url", "header"] + + web_urlfilter_table: + description: + - URL filter table ID. + required: false + + web_whitelist: + description: + - FortiGuard whitelist settings. + - FLAG Based Options. Specify multiple in list form. + - flag | exempt-av | Exempt antivirus. + - flag | exempt-webcontent | Exempt web content. + - flag | exempt-activex-java-cookie | Exempt ActiveX-JAVA-Cookie. + - flag | exempt-dlp | Exempt DLP. + - flag | exempt-rangeblock | Exempt RangeBlock. + - flag | extended-log-others | Support extended log. + required: false + choices: + - exempt-av + - exempt-webcontent + - exempt-activex-java-cookie + - exempt-dlp + - exempt-rangeblock + - extended-log-others + + web_youtube_restrict: + description: + - YouTube EDU filter level. + - choice | strict | Strict access for YouTube. + - choice | none | Full access for YouTube. + - choice | moderate | Moderate access for YouTube. + required: false + choices: ["strict", "none", "moderate"] + + youtube_channel_filter: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + youtube_channel_filter_channel_id: + description: + - YouTube channel ID to be filtered. + required: false + + youtube_channel_filter_comment: + description: + - Comment. + required: false + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + community.fortios.fmgr_secprof_web: + name: "Ansible_Web_Filter_Profile" + mode: "delete" + + - name: CREATE Profile + community.fortios.fmgr_secprof_web: + name: "Ansible_Web_Filter_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" + extended_log: "enable" + inspection_mode: "proxy" + log_all_url: "enable" + options: "js" + ovrd_perm: "bannedword-override" + post_action: "block" + web_content_log: "enable" + web_extended_all_action_log: "enable" + web_filter_activex_log: "enable" + web_filter_applet_log: "enable" + web_filter_command_block_log: "enable" + web_filter_cookie_log: "enable" + web_filter_cookie_removal_log: "enable" + web_filter_js_log: "enable" + web_filter_jscript_log: "enable" + web_filter_referer_log: "enable" + web_filter_unknown_log: "enable" + web_filter_vbs_log: "enable" + web_ftgd_err_log: "enable" + web_ftgd_quota_usage: "enable" + web_invalid_domain_log: "enable" + web_url_log: "enable" + wisp: "enable" + wisp_algorithm: "auto-learning" + youtube_channel_status: "blacklist" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: str +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.connection import Connection +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.fortimanager import FortiManagerHandler +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGBaseException +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRCommon +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FMGRMethods +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import DEFAULT_RESULT_OBJ +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import prepare_dict +from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import scrub_dict + + +def fmgr_webfilter_profile_modify(fmgr, paramgram): + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = DEFAULT_RESULT_OBJ + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/webfilter/profile'.format(adom=adom) + datagram = scrub_dict(prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/webfilter/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + response = fmgr.process_request(url, datagram, paramgram["mode"]) + + return response + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + youtube_channel_status=dict(required=False, type="str", choices=["disable", "blacklist", "whitelist"]), + wisp_servers=dict(required=False, type="str"), + wisp_algorithm=dict(required=False, type="str", choices=["auto-learning", "primary-secondary", "round-robin"]), + wisp=dict(required=False, type="str", choices=["disable", "enable"]), + web_url_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_invalid_domain_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_ftgd_quota_usage=dict(required=False, type="str", choices=["disable", "enable"]), + web_ftgd_err_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_vbs_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_unknown_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_referer_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_jscript_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_js_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_cookie_removal_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_cookie_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_command_block_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_applet_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_activex_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_extended_all_action_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_content_log=dict(required=False, type="str", choices=["disable", "enable"]), + replacemsg_group=dict(required=False, type="str"), + post_action=dict(required=False, type="str", choices=["normal", "block"]), + ovrd_perm=dict(required=False, type="list", choices=["bannedword-override", + "urlfilter-override", + "fortiguard-wf-override", + "contenttype-check-override"]), + options=dict(required=False, type="list", choices=["block-invalid-url", + "jscript", + "js", + "vbs", + "unknown", + "wf-referer", + "intrinsic", + "wf-cookie", + "per-user-bwl", + "activexfilter", + "cookiefilter", + "javafilter"]), + name=dict(required=False, type="str"), + log_all_url=dict(required=False, type="str", choices=["disable", "enable"]), + inspection_mode=dict(required=False, type="str", choices=["proxy", "flow-based"]), + https_replacemsg=dict(required=False, type="str", choices=["disable", "enable"]), + extended_log=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + ftgd_wf=dict(required=False, type="list"), + ftgd_wf_exempt_quota=dict(required=False, type="str"), + ftgd_wf_max_quota_timeout=dict(required=False, type="int"), + ftgd_wf_options=dict(required=False, type="str", choices=["error-allow", "rate-server-ip", + "connect-request-bypass", "ftgd-disable"]), + ftgd_wf_ovrd=dict(required=False, type="str"), + ftgd_wf_rate_crl_urls=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_rate_css_urls=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_rate_image_urls=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_rate_javascript_urls=dict(required=False, type="str", choices=["disable", "enable"]), + + ftgd_wf_filters_action=dict(required=False, type="str", choices=["block", "monitor", + "warning", "authenticate"]), + ftgd_wf_filters_auth_usr_grp=dict(required=False, type="str"), + ftgd_wf_filters_category=dict(required=False, type="str"), + ftgd_wf_filters_log=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_filters_override_replacemsg=dict(required=False, type="str"), + ftgd_wf_filters_warn_duration=dict(required=False, type="str"), + ftgd_wf_filters_warning_duration_type=dict(required=False, type="str", choices=["session", "timeout"]), + ftgd_wf_filters_warning_prompt=dict(required=False, type="str", choices=["per-domain", "per-category"]), + + ftgd_wf_quota_category=dict(required=False, type="str"), + ftgd_wf_quota_duration=dict(required=False, type="str"), + ftgd_wf_quota_override_replacemsg=dict(required=False, type="str"), + ftgd_wf_quota_type=dict(required=False, type="str", choices=["time", "traffic"]), + ftgd_wf_quota_unit=dict(required=False, type="str", choices=["B", "KB", "MB", "GB"]), + ftgd_wf_quota_value=dict(required=False, type="int"), + override=dict(required=False, type="list"), + override_ovrd_cookie=dict(required=False, type="str", choices=["deny", "allow"]), + override_ovrd_dur=dict(required=False, type="str"), + override_ovrd_dur_mode=dict(required=False, type="str", choices=["constant", "ask"]), + override_ovrd_scope=dict(required=False, type="str", choices=["user", "user-group", "ip", "ask", "browser"]), + override_ovrd_user_group=dict(required=False, type="str"), + override_profile=dict(required=False, type="str"), + override_profile_attribute=dict(required=False, type="list", choices=["User-Name", + "NAS-IP-Address", + "Framed-IP-Address", + "Framed-IP-Netmask", + "Filter-Id", + "Login-IP-Host", + "Reply-Message", + "Callback-Number", + "Callback-Id", + "Framed-Route", + "Framed-IPX-Network", + "Class", + "Called-Station-Id", + "Calling-Station-Id", + "NAS-Identifier", + "Proxy-State", + "Login-LAT-Service", + "Login-LAT-Node", + "Login-LAT-Group", + "Framed-AppleTalk-Zone", + "Acct-Session-Id", + "Acct-Multi-Session-Id"]), + override_profile_type=dict(required=False, type="str", choices=["list", "radius"]), + url_extraction=dict(required=False, type="list"), + url_extraction_redirect_header=dict(required=False, type="str"), + url_extraction_redirect_no_content=dict(required=False, type="str", choices=["disable", "enable"]), + url_extraction_redirect_url=dict(required=False, type="str"), + url_extraction_server_fqdn=dict(required=False, type="str"), + url_extraction_status=dict(required=False, type="str", choices=["disable", "enable"]), + web=dict(required=False, type="list"), + web_blacklist=dict(required=False, type="str", choices=["disable", "enable"]), + web_bword_table=dict(required=False, type="str"), + web_bword_threshold=dict(required=False, type="int"), + web_content_header_list=dict(required=False, type="str"), + web_keyword_match=dict(required=False, type="str"), + web_log_search=dict(required=False, type="str", choices=["disable", "enable"]), + web_safe_search=dict(required=False, type="str", choices=["url", "header"]), + web_urlfilter_table=dict(required=False, type="str"), + web_whitelist=dict(required=False, type="list", choices=["exempt-av", + "exempt-webcontent", + "exempt-activex-java-cookie", + "exempt-dlp", + "exempt-rangeblock", + "extended-log-others"]), + web_youtube_restrict=dict(required=False, type="str", choices=["strict", "none", "moderate"]), + youtube_channel_filter=dict(required=False, type="list"), + youtube_channel_filter_channel_id=dict(required=False, type="str"), + youtube_channel_filter_comment=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "youtube-channel-status": module.params["youtube_channel_status"], + "wisp-servers": module.params["wisp_servers"], + "wisp-algorithm": module.params["wisp_algorithm"], + "wisp": module.params["wisp"], + "web-url-log": module.params["web_url_log"], + "web-invalid-domain-log": module.params["web_invalid_domain_log"], + "web-ftgd-quota-usage": module.params["web_ftgd_quota_usage"], + "web-ftgd-err-log": module.params["web_ftgd_err_log"], + "web-filter-vbs-log": module.params["web_filter_vbs_log"], + "web-filter-unknown-log": module.params["web_filter_unknown_log"], + "web-filter-referer-log": module.params["web_filter_referer_log"], + "web-filter-jscript-log": module.params["web_filter_jscript_log"], + "web-filter-js-log": module.params["web_filter_js_log"], + "web-filter-cookie-removal-log": module.params["web_filter_cookie_removal_log"], + "web-filter-cookie-log": module.params["web_filter_cookie_log"], + "web-filter-command-block-log": module.params["web_filter_command_block_log"], + "web-filter-applet-log": module.params["web_filter_applet_log"], + "web-filter-activex-log": module.params["web_filter_activex_log"], + "web-extended-all-action-log": module.params["web_extended_all_action_log"], + "web-content-log": module.params["web_content_log"], + "replacemsg-group": module.params["replacemsg_group"], + "post-action": module.params["post_action"], + "ovrd-perm": module.params["ovrd_perm"], + "options": module.params["options"], + "name": module.params["name"], + "log-all-url": module.params["log_all_url"], + "inspection-mode": module.params["inspection_mode"], + "https-replacemsg": module.params["https_replacemsg"], + "extended-log": module.params["extended_log"], + "comment": module.params["comment"], + "ftgd-wf": { + "exempt-quota": module.params["ftgd_wf_exempt_quota"], + "max-quota-timeout": module.params["ftgd_wf_max_quota_timeout"], + "options": module.params["ftgd_wf_options"], + "ovrd": module.params["ftgd_wf_ovrd"], + "rate-crl-urls": module.params["ftgd_wf_rate_crl_urls"], + "rate-css-urls": module.params["ftgd_wf_rate_css_urls"], + "rate-image-urls": module.params["ftgd_wf_rate_image_urls"], + "rate-javascript-urls": module.params["ftgd_wf_rate_javascript_urls"], + "filters": { + "action": module.params["ftgd_wf_filters_action"], + "auth-usr-grp": module.params["ftgd_wf_filters_auth_usr_grp"], + "category": module.params["ftgd_wf_filters_category"], + "log": module.params["ftgd_wf_filters_log"], + "override-replacemsg": module.params["ftgd_wf_filters_override_replacemsg"], + "warn-duration": module.params["ftgd_wf_filters_warn_duration"], + "warning-duration-type": module.params["ftgd_wf_filters_warning_duration_type"], + "warning-prompt": module.params["ftgd_wf_filters_warning_prompt"], + }, + "quota": { + "category": module.params["ftgd_wf_quota_category"], + "duration": module.params["ftgd_wf_quota_duration"], + "override-replacemsg": module.params["ftgd_wf_quota_override_replacemsg"], + "type": module.params["ftgd_wf_quota_type"], + "unit": module.params["ftgd_wf_quota_unit"], + "value": module.params["ftgd_wf_quota_value"], + }, + }, + "override": { + "ovrd-cookie": module.params["override_ovrd_cookie"], + "ovrd-dur": module.params["override_ovrd_dur"], + "ovrd-dur-mode": module.params["override_ovrd_dur_mode"], + "ovrd-scope": module.params["override_ovrd_scope"], + "ovrd-user-group": module.params["override_ovrd_user_group"], + "profile": module.params["override_profile"], + "profile-attribute": module.params["override_profile_attribute"], + "profile-type": module.params["override_profile_type"], + }, + "url-extraction": { + "redirect-header": module.params["url_extraction_redirect_header"], + "redirect-no-content": module.params["url_extraction_redirect_no_content"], + "redirect-url": module.params["url_extraction_redirect_url"], + "server-fqdn": module.params["url_extraction_server_fqdn"], + "status": module.params["url_extraction_status"], + }, + "web": { + "blacklist": module.params["web_blacklist"], + "bword-table": module.params["web_bword_table"], + "bword-threshold": module.params["web_bword_threshold"], + "content-header-list": module.params["web_content_header_list"], + "keyword-match": module.params["web_keyword_match"], + "log-search": module.params["web_log_search"], + "safe-search": module.params["web_safe_search"], + "urlfilter-table": module.params["web_urlfilter_table"], + "whitelist": module.params["web_whitelist"], + "youtube-restrict": module.params["web_youtube_restrict"], + }, + "youtube-channel-filter": { + "channel-id": module.params["youtube_channel_filter_channel_id"], + "comment": module.params["youtube_channel_filter_comment"], + } + } + module.paramgram = paramgram + fmgr = None + if module._socket_path: + connection = Connection(module._socket_path) + fmgr = FortiManagerHandler(connection, module) + fmgr.tools = FMGRCommon() + else: + module.fail_json(**FAIL_SOCKET_MSG) + + list_overrides = ['ftgd-wf', 'override', 'url-extraction', 'web', 'youtube-channel-filter'] + paramgram = fmgr.tools.paramgram_child_list_override(list_overrides=list_overrides, + paramgram=paramgram, module=module) + + results = DEFAULT_RESULT_OBJ + + try: + + results = fmgr_webfilter_profile_modify(fmgr, paramgram) + fmgr.govern_response(module=module, results=results, + ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) + + except Exception as err: + raise FMGBaseException(err) + + return module.exit_json(**results[1]) + + +if __name__ == "__main__": + main() |