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 21__metaclass__ = type 22 23ANSIBLE_METADATA = {'status': ['preview'], 24 'supported_by': 'community', 25 'metadata_version': '1.1'} 26 27DOCUMENTATION = ''' 28--- 29module: fmgr_script 30version_added: "2.5" 31notes: 32 - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/). 33author: Andrew Welsh (@Ghilli3) 34short_description: Add/Edit/Delete and execute scripts 35description: Create/edit/delete scripts and execute the scripts on the FortiManager using jsonrpc API 36 37options: 38 adom: 39 description: 40 - The administrative domain (admon) the configuration belongs to 41 required: true 42 43 vdom: 44 description: 45 - The virtual domain (vdom) the configuration belongs to 46 47 mode: 48 description: 49 - The desired mode of the specified object. Execute will run the script. 50 required: false 51 default: "add" 52 choices: ["add", "delete", "execute", "set"] 53 version_added: "2.8" 54 55 script_name: 56 description: 57 - The name of the script. 58 required: True 59 60 script_type: 61 description: 62 - The type of script (CLI or TCL). 63 required: false 64 65 script_target: 66 description: 67 - The target of the script to be run. 68 required: false 69 70 script_description: 71 description: 72 - The description of the script. 73 required: false 74 75 script_content: 76 description: 77 - The script content that will be executed. 78 required: false 79 80 script_scope: 81 description: 82 - (datasource) The devices that the script will run on, can have both device member and device group member. 83 required: false 84 85 script_package: 86 description: 87 - (datasource) Policy package object to run the script against 88 required: false 89''' 90 91EXAMPLES = ''' 92- name: CREATE SCRIPT 93 fmgr_script: 94 adom: "root" 95 script_name: "TestScript" 96 script_type: "cli" 97 script_target: "remote_device" 98 script_description: "Create by Ansible" 99 script_content: "get system status" 100 101- name: EXECUTE SCRIPT 102 fmgr_script: 103 adom: "root" 104 script_name: "TestScript" 105 mode: "execute" 106 script_scope: "FGT1,FGT2" 107 108- name: DELETE SCRIPT 109 fmgr_script: 110 adom: "root" 111 script_name: "TestScript" 112 mode: "delete" 113''' 114 115RETURN = """ 116api_result: 117 description: full API response, includes status code and message 118 returned: always 119 type: str 120""" 121 122from ansible.module_utils.basic import AnsibleModule, env_fallback 123from ansible.module_utils.connection import Connection 124from ansible.module_utils.network.fortimanager.fortimanager import FortiManagerHandler 125from ansible.module_utils.network.fortimanager.common import FMGBaseException 126from ansible.module_utils.network.fortimanager.common import FMGRCommon 127from ansible.module_utils.network.fortimanager.common import FMGRMethods 128from ansible.module_utils.network.fortimanager.common import DEFAULT_RESULT_OBJ 129from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 130 131 132def set_script(fmgr, paramgram): 133 """ 134 :param fmgr: The fmgr object instance from fortimanager.py 135 :type fmgr: class object 136 :param paramgram: The formatted dictionary of options to process 137 :type paramgram: dict 138 :return: The response from the FortiManager 139 :rtype: dict 140 """ 141 142 datagram = { 143 'content': paramgram["script_content"], 144 'desc': paramgram["script_description"], 145 'name': paramgram["script_name"], 146 'target': paramgram["script_target"], 147 'type': paramgram["script_type"], 148 } 149 150 url = '/dvmdb/adom/{adom}/script/'.format(adom=paramgram["adom"]) 151 response = fmgr.process_request(url, datagram, FMGRMethods.SET) 152 return response 153 154 155def delete_script(fmgr, paramgram): 156 """ 157 :param fmgr: The fmgr object instance from fortimanager.py 158 :type fmgr: class object 159 :param paramgram: The formatted dictionary of options to process 160 :type paramgram: dict 161 :return: The response from the FortiManager 162 :rtype: dict 163 """ 164 165 datagram = { 166 'name': paramgram["script_name"], 167 } 168 169 url = '/dvmdb/adom/{adom}/script/{script_name}'.format(adom=paramgram["adom"], script_name=paramgram["script_name"]) 170 response = fmgr.process_request(url, datagram, FMGRMethods.DELETE) 171 return response 172 173 174def execute_script(fmgr, paramgram): 175 """ 176 :param fmgr: The fmgr object instance from fortimanager.py 177 :type fmgr: class object 178 :param paramgram: The formatted dictionary of options to process 179 :type paramgram: dict 180 :return: The response from the FortiManager 181 :rtype: dict 182 """ 183 184 scope_list = list() 185 scope = paramgram["script_scope"].replace(' ', '') 186 scope = scope.split(',') 187 for dev_name in scope: 188 scope_list.append({'name': dev_name, 'vdom': paramgram["vdom"]}) 189 190 datagram = { 191 'adom': paramgram["adom"], 192 'script': paramgram["script_name"], 193 'package': paramgram["script_package"], 194 'scope': scope_list, 195 } 196 197 url = '/dvmdb/adom/{adom}/script/execute'.format(adom=paramgram["adom"]) 198 response = fmgr.process_request(url, datagram, FMGRMethods.EXEC) 199 return response 200 201 202def main(): 203 argument_spec = dict( 204 adom=dict(required=False, type="str", default="root"), 205 vdom=dict(required=False, type="str", default="root"), 206 mode=dict(choices=["add", "execute", "set", "delete"], type="str", default="add"), 207 script_name=dict(required=True, type="str"), 208 script_type=dict(required=False, type="str"), 209 script_target=dict(required=False, type="str"), 210 script_description=dict(required=False, type="str"), 211 script_content=dict(required=False, type="str"), 212 script_scope=dict(required=False, type="str"), 213 script_package=dict(required=False, type="str"), 214 ) 215 216 module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, ) 217 paramgram = { 218 "script_name": module.params["script_name"], 219 "script_type": module.params["script_type"], 220 "script_target": module.params["script_target"], 221 "script_description": module.params["script_description"], 222 "script_content": module.params["script_content"], 223 "script_scope": module.params["script_scope"], 224 "script_package": module.params["script_package"], 225 "adom": module.params["adom"], 226 "vdom": module.params["vdom"], 227 "mode": module.params["mode"], 228 } 229 module.paramgram = paramgram 230 fmgr = None 231 if module._socket_path: 232 connection = Connection(module._socket_path) 233 fmgr = FortiManagerHandler(connection, module) 234 fmgr.tools = FMGRCommon() 235 else: 236 module.fail_json(**FAIL_SOCKET_MSG) 237 238 results = DEFAULT_RESULT_OBJ 239 240 try: 241 if paramgram["mode"] in ['add', 'set']: 242 results = set_script(fmgr, paramgram) 243 fmgr.govern_response(module=module, results=results, msg="Operation Finished", 244 ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params)) 245 except Exception as err: 246 raise FMGBaseException(err) 247 248 try: 249 if paramgram["mode"] == "execute": 250 results = execute_script(fmgr, paramgram) 251 fmgr.govern_response(module=module, results=results, msg="Operation Finished", 252 ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params)) 253 except Exception as err: 254 raise FMGBaseException(err) 255 256 try: 257 if paramgram["mode"] == "delete": 258 results = delete_script(fmgr, paramgram) 259 fmgr.govern_response(module=module, results=results, msg="Operation Finished", 260 ansible_facts=fmgr.construct_ansible_facts(results, module.params, module.params)) 261 except Exception as err: 262 raise FMGBaseException(err) 263 264 return module.exit_json(**results[1]) 265 266 267if __name__ == "__main__": 268 main() 269