1#!/usr/bin/python 2# 3# This file is part of Ansible 4# 5# Ansible is free software: you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation, either version 3 of the License, or 8# (at your option) any later version. 9# 10# Ansible is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with Ansible. If not, see <http://www.gnu.org/licenses/>. 17# 18 19from __future__ import absolute_import, division, print_function 20__metaclass__ = type 21 22ANSIBLE_METADATA = { 23 "metadata_version": "1.1", 24 "status": ["preview"], 25 "supported_by": "community" 26} 27 28DOCUMENTATION = ''' 29--- 30module: fmgr_device_config 31version_added: "2.8" 32notes: 33 - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). 34author: 35 - Luke Weighall (@lweighall) 36 - Andrew Welsh (@Ghilli3) 37 - Jim Huber (@p4r4n0y1ng) 38short_description: Edit device configurations 39description: 40 - Edit device configurations from FortiManager Device Manager using JSON RPC API. 41 42options: 43 adom: 44 description: 45 - The ADOM the configuration should belong to. 46 required: false 47 default: root 48 49 device_unique_name: 50 description: 51 - The unique device's name that you are editing. A.K.A. Friendly name of the device in FortiManager. 52 required: True 53 54 device_hostname: 55 description: 56 - The device's new hostname. 57 required: false 58 59 install_config: 60 description: 61 - Tells FMGR to attempt to install the config after making it. 62 required: false 63 default: disable 64 65 interface: 66 description: 67 - The interface/port number you are editing. 68 required: false 69 70 interface_ip: 71 description: 72 - The IP and subnet of the interface/port you are editing. 73 required: false 74 75 interface_allow_access: 76 description: 77 - Specify what protocols are allowed on the interface, comma-separated list (see examples). 78 required: false 79''' 80 81EXAMPLES = ''' 82- name: CHANGE HOSTNAME 83 fmgr_device_config: 84 device_hostname: "ChangedbyAnsible" 85 device_unique_name: "FGT1" 86 87- name: EDIT INTERFACE INFORMATION 88 fmgr_device_config: 89 adom: "root" 90 device_unique_name: "FGT2" 91 interface: "port3" 92 interface_ip: "10.1.1.1/24" 93 interface_allow_access: "ping, telnet, https" 94 95- name: INSTALL CONFIG 96 fmgr_device_config: 97 adom: "root" 98 device_unique_name: "FGT1" 99 install_config: "enable" 100''' 101 102RETURN = """ 103api_result: 104 description: full API response, includes status code and message 105 returned: always 106 type: str 107""" 108 109from ansible.module_utils.basic import AnsibleModule 110from ansible.module_utils.connection import Connection 111from ansible.module_utils.network.fortimanager.fortimanager import FortiManagerHandler 112from ansible.module_utils.network.fortimanager.common import FMGBaseException 113from ansible.module_utils.network.fortimanager.common import FMGRCommon 114from ansible.module_utils.network.fortimanager.common import DEFAULT_RESULT_OBJ 115from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 116from ansible.module_utils.network.fortimanager.common import FMGRMethods 117 118 119def update_device_hostname(fmgr, paramgram): 120 """ 121 :param fmgr: The fmgr object instance from fortimanager.py 122 :type fmgr: class object 123 :param paramgram: The formatted dictionary of options to process 124 :type paramgram: dict 125 :return: The response from the FortiManager 126 :rtype: dict 127 """ 128 datagram = { 129 "hostname": paramgram["device_hostname"] 130 } 131 132 url = "pm/config/device/{device_name}/global/system/global".format(device_name=paramgram["device_unique_name"]) 133 response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE) 134 return response 135 136 137def update_device_interface(fmgr, paramgram): 138 """ 139 :param fmgr: The fmgr object instance from fortimanager.py 140 :type fmgr: class object 141 :param paramgram: The formatted dictionary of options to process 142 :type paramgram: dict 143 :return: The response from the FortiManager 144 :rtype: dict 145 """ 146 access_list = list() 147 allow_access_list = paramgram["interface_allow_access"].replace(' ', '') 148 access_list = allow_access_list.split(',') 149 150 datagram = { 151 "allowaccess": access_list, 152 "ip": paramgram["interface_ip"] 153 } 154 155 url = "/pm/config/device/{device_name}/global/system/interface" \ 156 "/{interface}".format(device_name=paramgram["device_unique_name"], interface=paramgram["interface"]) 157 response = fmgr.process_request(url, datagram, FMGRMethods.UPDATE) 158 return response 159 160 161def exec_config(fmgr, paramgram): 162 """ 163 :param fmgr: The fmgr object instance from fortimanager.py 164 :type fmgr: class object 165 :param paramgram: The formatted dictionary of options to process 166 :type paramgram: dict 167 :return: The response from the FortiManager 168 :rtype: dict 169 """ 170 datagram = { 171 "scope": { 172 "name": paramgram["device_unique_name"] 173 }, 174 "adom": paramgram["adom"], 175 "flags": "none" 176 } 177 178 url = "/securityconsole/install/device" 179 response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) 180 return response 181 182 183def main(): 184 argument_spec = dict( 185 adom=dict(required=False, type="str", default="root"), 186 device_unique_name=dict(required=True, type="str"), 187 device_hostname=dict(required=False, type="str"), 188 interface=dict(required=False, type="str"), 189 interface_ip=dict(required=False, type="str"), 190 interface_allow_access=dict(required=False, type="str"), 191 install_config=dict(required=False, type="str", default="disable"), 192 ) 193 194 module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) 195 paramgram = { 196 "device_unique_name": module.params["device_unique_name"], 197 "device_hostname": module.params["device_hostname"], 198 "interface": module.params["interface"], 199 "interface_ip": module.params["interface_ip"], 200 "interface_allow_access": module.params["interface_allow_access"], 201 "install_config": module.params["install_config"], 202 "adom": module.params["adom"] 203 } 204 module.paramgram = paramgram 205 fmgr = None 206 if module._socket_path: 207 connection = Connection(module._socket_path) 208 fmgr = FortiManagerHandler(connection, module) 209 fmgr.tools = FMGRCommon() 210 else: 211 module.fail_json(**FAIL_SOCKET_MSG) 212 213 # BEGIN MODULE-SPECIFIC LOGIC -- THINGS NEED TO HAPPEN DEPENDING ON THE ENDPOINT AND OPERATION 214 results = DEFAULT_RESULT_OBJ 215 try: 216 if paramgram["device_hostname"] is not None: 217 results = update_device_hostname(fmgr, paramgram) 218 fmgr.govern_response(module=module, results=results, 219 ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) 220 221 if paramgram["interface_ip"] is not None or paramgram["interface_allow_access"] is not None: 222 results = update_device_interface(fmgr, paramgram) 223 fmgr.govern_response(module=module, results=results, 224 ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) 225 226 if paramgram["install_config"] == "enable": 227 results = exec_config(fmgr, paramgram) 228 fmgr.govern_response(module=module, results=results, 229 ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram)) 230 231 except Exception as err: 232 raise FMGBaseException(err) 233 234 return module.exit_json(**results[1]) 235 236 237if __name__ == "__main__": 238 main() 239