1#!/usr/bin/python 2from __future__ import (absolute_import, division, print_function) 3# Copyright 2019 Fortinet, Inc. 4# 5# This program 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# This program 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 this program. If not, see <https://www.gnu.org/licenses/>. 17 18__metaclass__ = type 19 20ANSIBLE_METADATA = {'status': ['preview'], 21 'supported_by': 'community', 22 'metadata_version': '1.1'} 23 24DOCUMENTATION = ''' 25--- 26module: fortios_system_autoupdate_tunneling 27short_description: Configure web proxy tunnelling for the FDN in Fortinet's FortiOS and FortiGate. 28description: 29 - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the 30 user to set and modify system_autoupdate feature and tunneling category. 31 Examples include all parameters and values need to be adjusted to datasources before usage. 32 Tested with FOS v6.0.5 33version_added: "2.9" 34author: 35 - Miguel Angel Munoz (@mamunozgonzalez) 36 - Nicolas Thomas (@thomnico) 37notes: 38 - Requires fortiosapi library developed by Fortinet 39 - Run as a local_action in your playbook 40requirements: 41 - fortiosapi>=0.9.8 42options: 43 host: 44 description: 45 - FortiOS or FortiGate IP address. 46 type: str 47 required: false 48 username: 49 description: 50 - FortiOS or FortiGate username. 51 type: str 52 required: false 53 password: 54 description: 55 - FortiOS or FortiGate password. 56 type: str 57 default: "" 58 vdom: 59 description: 60 - Virtual domain, among those defined previously. A vdom is a 61 virtual instance of the FortiGate that can be configured and 62 used as a different unit. 63 type: str 64 default: root 65 https: 66 description: 67 - Indicates if the requests towards FortiGate must use HTTPS protocol. 68 type: bool 69 default: true 70 ssl_verify: 71 description: 72 - Ensures FortiGate certificate must be verified by a proper CA. 73 type: bool 74 default: true 75 system_autoupdate_tunneling: 76 description: 77 - Configure web proxy tunnelling for the FDN. 78 default: null 79 type: dict 80 suboptions: 81 address: 82 description: 83 - Web proxy IP address or FQDN. 84 type: str 85 password: 86 description: 87 - Web proxy password. 88 type: str 89 port: 90 description: 91 - Web proxy port. 92 type: int 93 status: 94 description: 95 - Enable/disable web proxy tunnelling. 96 type: str 97 choices: 98 - enable 99 - disable 100 username: 101 description: 102 - Web proxy username. 103 type: str 104''' 105 106EXAMPLES = ''' 107- hosts: localhost 108 vars: 109 host: "192.168.122.40" 110 username: "admin" 111 password: "" 112 vdom: "root" 113 ssl_verify: "False" 114 tasks: 115 - name: Configure web proxy tunnelling for the FDN. 116 fortios_system_autoupdate_tunneling: 117 host: "{{ host }}" 118 username: "{{ username }}" 119 password: "{{ password }}" 120 vdom: "{{ vdom }}" 121 https: "False" 122 system_autoupdate_tunneling: 123 address: "<your_own_value>" 124 password: "<your_own_value>" 125 port: "5" 126 status: "enable" 127 username: "<your_own_value>" 128''' 129 130RETURN = ''' 131build: 132 description: Build number of the fortigate image 133 returned: always 134 type: str 135 sample: '1547' 136http_method: 137 description: Last method used to provision the content into FortiGate 138 returned: always 139 type: str 140 sample: 'PUT' 141http_status: 142 description: Last result given by FortiGate on last operation applied 143 returned: always 144 type: str 145 sample: "200" 146mkey: 147 description: Master key (id) used in the last call to FortiGate 148 returned: success 149 type: str 150 sample: "id" 151name: 152 description: Name of the table used to fulfill the request 153 returned: always 154 type: str 155 sample: "urlfilter" 156path: 157 description: Path of the table used to fulfill the request 158 returned: always 159 type: str 160 sample: "webfilter" 161revision: 162 description: Internal revision number 163 returned: always 164 type: str 165 sample: "17.0.2.10658" 166serial: 167 description: Serial number of the unit 168 returned: always 169 type: str 170 sample: "FGVMEVYYQT3AB5352" 171status: 172 description: Indication of the operation's result 173 returned: always 174 type: str 175 sample: "success" 176vdom: 177 description: Virtual domain used 178 returned: always 179 type: str 180 sample: "root" 181version: 182 description: Version of the FortiGate 183 returned: always 184 type: str 185 sample: "v5.6.3" 186 187''' 188 189from ansible.module_utils.basic import AnsibleModule 190from ansible.module_utils.connection import Connection 191from ansible.module_utils.network.fortios.fortios import FortiOSHandler 192from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 193 194 195def login(data, fos): 196 host = data['host'] 197 username = data['username'] 198 password = data['password'] 199 ssl_verify = data['ssl_verify'] 200 201 fos.debug('on') 202 if 'https' in data and not data['https']: 203 fos.https('off') 204 else: 205 fos.https('on') 206 207 fos.login(host, username, password, verify=ssl_verify) 208 209 210def filter_system_autoupdate_tunneling_data(json): 211 option_list = ['address', 'password', 'port', 212 'status', 'username'] 213 dictionary = {} 214 215 for attribute in option_list: 216 if attribute in json and json[attribute] is not None: 217 dictionary[attribute] = json[attribute] 218 219 return dictionary 220 221 222def underscore_to_hyphen(data): 223 if isinstance(data, list): 224 for elem in data: 225 elem = underscore_to_hyphen(elem) 226 elif isinstance(data, dict): 227 new_data = {} 228 for k, v in data.items(): 229 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 230 data = new_data 231 232 return data 233 234 235def system_autoupdate_tunneling(data, fos): 236 vdom = data['vdom'] 237 system_autoupdate_tunneling_data = data['system_autoupdate_tunneling'] 238 filtered_data = underscore_to_hyphen(filter_system_autoupdate_tunneling_data(system_autoupdate_tunneling_data)) 239 240 return fos.set('system.autoupdate', 241 'tunneling', 242 data=filtered_data, 243 vdom=vdom) 244 245 246def is_successful_status(status): 247 return status['status'] == "success" or \ 248 status['http_method'] == "DELETE" and status['http_status'] == 404 249 250 251def fortios_system_autoupdate(data, fos): 252 253 if data['system_autoupdate_tunneling']: 254 resp = system_autoupdate_tunneling(data, fos) 255 256 return not is_successful_status(resp), \ 257 resp['status'] == "success", \ 258 resp 259 260 261def main(): 262 fields = { 263 "host": {"required": False, "type": "str"}, 264 "username": {"required": False, "type": "str"}, 265 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 266 "vdom": {"required": False, "type": "str", "default": "root"}, 267 "https": {"required": False, "type": "bool", "default": True}, 268 "ssl_verify": {"required": False, "type": "bool", "default": True}, 269 "system_autoupdate_tunneling": { 270 "required": False, "type": "dict", "default": None, 271 "options": { 272 "address": {"required": False, "type": "str"}, 273 "password": {"required": False, "type": "str", "no_log": True}, 274 "port": {"required": False, "type": "int"}, 275 "status": {"required": False, "type": "str", 276 "choices": ["enable", "disable"]}, 277 "username": {"required": False, "type": "str"} 278 279 } 280 } 281 } 282 283 module = AnsibleModule(argument_spec=fields, 284 supports_check_mode=False) 285 286 # legacy_mode refers to using fortiosapi instead of HTTPAPI 287 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 288 'username' in module.params and module.params['username'] is not None and \ 289 'password' in module.params and module.params['password'] is not None 290 291 if not legacy_mode: 292 if module._socket_path: 293 connection = Connection(module._socket_path) 294 fos = FortiOSHandler(connection) 295 296 is_error, has_changed, result = fortios_system_autoupdate(module.params, fos) 297 else: 298 module.fail_json(**FAIL_SOCKET_MSG) 299 else: 300 try: 301 from fortiosapi import FortiOSAPI 302 except ImportError: 303 module.fail_json(msg="fortiosapi module is required") 304 305 fos = FortiOSAPI() 306 307 login(module.params, fos) 308 is_error, has_changed, result = fortios_system_autoupdate(module.params, fos) 309 fos.logout() 310 311 if not is_error: 312 module.exit_json(changed=has_changed, meta=result) 313 else: 314 module.fail_json(msg="Error in repo", meta=result) 315 316 317if __name__ == '__main__': 318 main() 319