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_webfilter_ips_urlfilter_setting 27short_description: Configure IPS URL filter settings 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 webfilter feature and ips_urlfilter_setting 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.8" 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 version_added: 2.9 76 webfilter_ips_urlfilter_setting: 77 description: 78 - Configure IPS URL filter settings. 79 default: null 80 type: dict 81 suboptions: 82 device: 83 description: 84 - Interface for this route. Source system.interface.name. 85 type: str 86 distance: 87 description: 88 - Administrative distance (1 - 255) for this route. 89 type: int 90 gateway: 91 description: 92 - Gateway IP address for this route. 93 type: str 94 geo_filter: 95 description: 96 - Filter based on geographical location. Route will NOT be installed if the resolved IP address belongs to the country in the filter. 97 type: str 98''' 99 100EXAMPLES = ''' 101- hosts: localhost 102 vars: 103 host: "192.168.122.40" 104 username: "admin" 105 password: "" 106 vdom: "root" 107 ssl_verify: "False" 108 tasks: 109 - name: Configure IPS URL filter settings. 110 fortios_webfilter_ips_urlfilter_setting: 111 host: "{{ host }}" 112 username: "{{ username }}" 113 password: "{{ password }}" 114 vdom: "{{ vdom }}" 115 https: "False" 116 webfilter_ips_urlfilter_setting: 117 device: "<your_own_value> (source system.interface.name)" 118 distance: "4" 119 gateway: "<your_own_value>" 120 geo_filter: "<your_own_value>" 121''' 122 123RETURN = ''' 124build: 125 description: Build number of the fortigate image 126 returned: always 127 type: str 128 sample: '1547' 129http_method: 130 description: Last method used to provision the content into FortiGate 131 returned: always 132 type: str 133 sample: 'PUT' 134http_status: 135 description: Last result given by FortiGate on last operation applied 136 returned: always 137 type: str 138 sample: "200" 139mkey: 140 description: Master key (id) used in the last call to FortiGate 141 returned: success 142 type: str 143 sample: "id" 144name: 145 description: Name of the table used to fulfill the request 146 returned: always 147 type: str 148 sample: "urlfilter" 149path: 150 description: Path of the table used to fulfill the request 151 returned: always 152 type: str 153 sample: "webfilter" 154revision: 155 description: Internal revision number 156 returned: always 157 type: str 158 sample: "17.0.2.10658" 159serial: 160 description: Serial number of the unit 161 returned: always 162 type: str 163 sample: "FGVMEVYYQT3AB5352" 164status: 165 description: Indication of the operation's result 166 returned: always 167 type: str 168 sample: "success" 169vdom: 170 description: Virtual domain used 171 returned: always 172 type: str 173 sample: "root" 174version: 175 description: Version of the FortiGate 176 returned: always 177 type: str 178 sample: "v5.6.3" 179 180''' 181 182from ansible.module_utils.basic import AnsibleModule 183from ansible.module_utils.connection import Connection 184from ansible.module_utils.network.fortios.fortios import FortiOSHandler 185from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 186 187 188def login(data, fos): 189 host = data['host'] 190 username = data['username'] 191 password = data['password'] 192 ssl_verify = data['ssl_verify'] 193 194 fos.debug('on') 195 if 'https' in data and not data['https']: 196 fos.https('off') 197 else: 198 fos.https('on') 199 200 fos.login(host, username, password, verify=ssl_verify) 201 202 203def filter_webfilter_ips_urlfilter_setting_data(json): 204 option_list = ['device', 'distance', 'gateway', 205 'geo_filter'] 206 dictionary = {} 207 208 for attribute in option_list: 209 if attribute in json and json[attribute] is not None: 210 dictionary[attribute] = json[attribute] 211 212 return dictionary 213 214 215def underscore_to_hyphen(data): 216 if isinstance(data, list): 217 for elem in data: 218 elem = underscore_to_hyphen(elem) 219 elif isinstance(data, dict): 220 new_data = {} 221 for k, v in data.items(): 222 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 223 data = new_data 224 225 return data 226 227 228def webfilter_ips_urlfilter_setting(data, fos): 229 vdom = data['vdom'] 230 webfilter_ips_urlfilter_setting_data = data['webfilter_ips_urlfilter_setting'] 231 filtered_data = underscore_to_hyphen(filter_webfilter_ips_urlfilter_setting_data(webfilter_ips_urlfilter_setting_data)) 232 233 return fos.set('webfilter', 234 'ips-urlfilter-setting', 235 data=filtered_data, 236 vdom=vdom) 237 238 239def is_successful_status(status): 240 return status['status'] == "success" or \ 241 status['http_method'] == "DELETE" and status['http_status'] == 404 242 243 244def fortios_webfilter(data, fos): 245 246 if data['webfilter_ips_urlfilter_setting']: 247 resp = webfilter_ips_urlfilter_setting(data, fos) 248 249 return not is_successful_status(resp), \ 250 resp['status'] == "success", \ 251 resp 252 253 254def main(): 255 fields = { 256 "host": {"required": False, "type": "str"}, 257 "username": {"required": False, "type": "str"}, 258 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 259 "vdom": {"required": False, "type": "str", "default": "root"}, 260 "https": {"required": False, "type": "bool", "default": True}, 261 "ssl_verify": {"required": False, "type": "bool", "default": True}, 262 "webfilter_ips_urlfilter_setting": { 263 "required": False, "type": "dict", "default": None, 264 "options": { 265 "device": {"required": False, "type": "str"}, 266 "distance": {"required": False, "type": "int"}, 267 "gateway": {"required": False, "type": "str"}, 268 "geo_filter": {"required": False, "type": "str"} 269 270 } 271 } 272 } 273 274 module = AnsibleModule(argument_spec=fields, 275 supports_check_mode=False) 276 277 # legacy_mode refers to using fortiosapi instead of HTTPAPI 278 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 279 'username' in module.params and module.params['username'] is not None and \ 280 'password' in module.params and module.params['password'] is not None 281 282 if not legacy_mode: 283 if module._socket_path: 284 connection = Connection(module._socket_path) 285 fos = FortiOSHandler(connection) 286 287 is_error, has_changed, result = fortios_webfilter(module.params, fos) 288 else: 289 module.fail_json(**FAIL_SOCKET_MSG) 290 else: 291 try: 292 from fortiosapi import FortiOSAPI 293 except ImportError: 294 module.fail_json(msg="fortiosapi module is required") 295 296 fos = FortiOSAPI() 297 298 login(module.params, fos) 299 is_error, has_changed, result = fortios_webfilter(module.params, fos) 300 fos.logout() 301 302 if not is_error: 303 module.exit_json(changed=has_changed, meta=result) 304 else: 305 module.fail_json(msg="Error in repo", meta=result) 306 307 308if __name__ == '__main__': 309 main() 310