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_dlp_filepattern 27short_description: Configure file patterns used by DLP blocking 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 dlp feature and filepattern 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 state: 77 description: 78 - Indicates whether to create or remove the object. 79 This attribute was present already in previous version in a deeper level. 80 It has been moved out to this outer level. 81 type: str 82 required: false 83 choices: 84 - present 85 - absent 86 version_added: 2.9 87 dlp_filepattern: 88 description: 89 - Configure file patterns used by DLP blocking. 90 default: null 91 type: dict 92 suboptions: 93 state: 94 description: 95 - B(Deprecated) 96 - Starting with Ansible 2.9 we recommend using the top-level 'state' parameter. 97 - HORIZONTALLINE 98 - Indicates whether to create or remove the object. 99 type: str 100 required: false 101 choices: 102 - present 103 - absent 104 comment: 105 description: 106 - Optional comments. 107 type: str 108 entries: 109 description: 110 - Configure file patterns used by DLP blocking. 111 type: list 112 suboptions: 113 file_type: 114 description: 115 - Select a file type. 116 type: str 117 choices: 118 - 7z 119 - arj 120 - cab 121 - lzh 122 - rar 123 - tar 124 - zip 125 - bzip 126 - gzip 127 - bzip2 128 - xz 129 - bat 130 - msc 131 - uue 132 - mime 133 - base64 134 - binhex 135 - elf 136 - exe 137 - hta 138 - html 139 - jad 140 - class 141 - cod 142 - javascript 143 - msoffice 144 - msofficex 145 - fsg 146 - upx 147 - petite 148 - aspack 149 - sis 150 - hlp 151 - activemime 152 - jpeg 153 - gif 154 - tiff 155 - png 156 - bmp 157 - ignored 158 - unknown 159 - mpeg 160 - mov 161 - mp3 162 - wma 163 - wav 164 - pdf 165 - avi 166 - rm 167 - torrent 168 - hibun 169 - msi 170 - mach-o 171 - dmg 172 - .net 173 - xar 174 - chm 175 - iso 176 - crx 177 filter_type: 178 description: 179 - Filter by file name pattern or by file type. 180 type: str 181 choices: 182 - pattern 183 - type 184 pattern: 185 description: 186 - Add a file name pattern. 187 required: true 188 type: str 189 id: 190 description: 191 - ID. 192 required: true 193 type: int 194 name: 195 description: 196 - Name of table containing the file pattern list. 197 type: str 198''' 199 200EXAMPLES = ''' 201- hosts: localhost 202 vars: 203 host: "192.168.122.40" 204 username: "admin" 205 password: "" 206 vdom: "root" 207 ssl_verify: "False" 208 tasks: 209 - name: Configure file patterns used by DLP blocking. 210 fortios_dlp_filepattern: 211 host: "{{ host }}" 212 username: "{{ username }}" 213 password: "{{ password }}" 214 vdom: "{{ vdom }}" 215 https: "False" 216 state: "present" 217 dlp_filepattern: 218 comment: "Optional comments." 219 entries: 220 - 221 file_type: "7z" 222 filter_type: "pattern" 223 pattern: "<your_own_value>" 224 id: "8" 225 name: "default_name_9" 226''' 227 228RETURN = ''' 229build: 230 description: Build number of the fortigate image 231 returned: always 232 type: str 233 sample: '1547' 234http_method: 235 description: Last method used to provision the content into FortiGate 236 returned: always 237 type: str 238 sample: 'PUT' 239http_status: 240 description: Last result given by FortiGate on last operation applied 241 returned: always 242 type: str 243 sample: "200" 244mkey: 245 description: Master key (id) used in the last call to FortiGate 246 returned: success 247 type: str 248 sample: "id" 249name: 250 description: Name of the table used to fulfill the request 251 returned: always 252 type: str 253 sample: "urlfilter" 254path: 255 description: Path of the table used to fulfill the request 256 returned: always 257 type: str 258 sample: "webfilter" 259revision: 260 description: Internal revision number 261 returned: always 262 type: str 263 sample: "17.0.2.10658" 264serial: 265 description: Serial number of the unit 266 returned: always 267 type: str 268 sample: "FGVMEVYYQT3AB5352" 269status: 270 description: Indication of the operation's result 271 returned: always 272 type: str 273 sample: "success" 274vdom: 275 description: Virtual domain used 276 returned: always 277 type: str 278 sample: "root" 279version: 280 description: Version of the FortiGate 281 returned: always 282 type: str 283 sample: "v5.6.3" 284 285''' 286 287from ansible.module_utils.basic import AnsibleModule 288from ansible.module_utils.connection import Connection 289from ansible.module_utils.network.fortios.fortios import FortiOSHandler 290from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 291 292 293def login(data, fos): 294 host = data['host'] 295 username = data['username'] 296 password = data['password'] 297 ssl_verify = data['ssl_verify'] 298 299 fos.debug('on') 300 if 'https' in data and not data['https']: 301 fos.https('off') 302 else: 303 fos.https('on') 304 305 fos.login(host, username, password, verify=ssl_verify) 306 307 308def filter_dlp_filepattern_data(json): 309 option_list = ['comment', 'entries', 'id', 310 'name'] 311 dictionary = {} 312 313 for attribute in option_list: 314 if attribute in json and json[attribute] is not None: 315 dictionary[attribute] = json[attribute] 316 317 return dictionary 318 319 320def underscore_to_hyphen(data): 321 if isinstance(data, list): 322 for elem in data: 323 elem = underscore_to_hyphen(elem) 324 elif isinstance(data, dict): 325 new_data = {} 326 for k, v in data.items(): 327 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 328 data = new_data 329 330 return data 331 332 333def dlp_filepattern(data, fos): 334 vdom = data['vdom'] 335 if 'state' in data and data['state']: 336 state = data['state'] 337 elif 'state' in data['dlp_filepattern'] and data['dlp_filepattern']: 338 state = data['dlp_filepattern']['state'] 339 else: 340 state = True 341 dlp_filepattern_data = data['dlp_filepattern'] 342 filtered_data = underscore_to_hyphen(filter_dlp_filepattern_data(dlp_filepattern_data)) 343 344 if state == "present": 345 return fos.set('dlp', 346 'filepattern', 347 data=filtered_data, 348 vdom=vdom) 349 350 elif state == "absent": 351 return fos.delete('dlp', 352 'filepattern', 353 mkey=filtered_data['id'], 354 vdom=vdom) 355 356 357def is_successful_status(status): 358 return status['status'] == "success" or \ 359 status['http_method'] == "DELETE" and status['http_status'] == 404 360 361 362def fortios_dlp(data, fos): 363 364 if data['dlp_filepattern']: 365 resp = dlp_filepattern(data, fos) 366 367 return not is_successful_status(resp), \ 368 resp['status'] == "success", \ 369 resp 370 371 372def main(): 373 fields = { 374 "host": {"required": False, "type": "str"}, 375 "username": {"required": False, "type": "str"}, 376 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 377 "vdom": {"required": False, "type": "str", "default": "root"}, 378 "https": {"required": False, "type": "bool", "default": True}, 379 "ssl_verify": {"required": False, "type": "bool", "default": True}, 380 "state": {"required": False, "type": "str", 381 "choices": ["present", "absent"]}, 382 "dlp_filepattern": { 383 "required": False, "type": "dict", "default": None, 384 "options": { 385 "state": {"required": False, "type": "str", 386 "choices": ["present", "absent"]}, 387 "comment": {"required": False, "type": "str"}, 388 "entries": {"required": False, "type": "list", 389 "options": { 390 "file_type": {"required": False, "type": "str", 391 "choices": ["7z", "arj", "cab", 392 "lzh", "rar", "tar", 393 "zip", "bzip", "gzip", 394 "bzip2", "xz", "bat", 395 "msc", "uue", "mime", 396 "base64", "binhex", "elf", 397 "exe", "hta", "html", 398 "jad", "class", "cod", 399 "javascript", "msoffice", "msofficex", 400 "fsg", "upx", "petite", 401 "aspack", "sis", "hlp", 402 "activemime", "jpeg", "gif", 403 "tiff", "png", "bmp", 404 "ignored", "unknown", "mpeg", 405 "mov", "mp3", "wma", 406 "wav", "pdf", "avi", 407 "rm", "torrent", "hibun", 408 "msi", "mach-o", "dmg", 409 ".net", "xar", "chm", 410 "iso", "crx"]}, 411 "filter_type": {"required": False, "type": "str", 412 "choices": ["pattern", "type"]}, 413 "pattern": {"required": True, "type": "str"} 414 }}, 415 "id": {"required": True, "type": "int"}, 416 "name": {"required": False, "type": "str"} 417 418 } 419 } 420 } 421 422 module = AnsibleModule(argument_spec=fields, 423 supports_check_mode=False) 424 425 # legacy_mode refers to using fortiosapi instead of HTTPAPI 426 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 427 'username' in module.params and module.params['username'] is not None and \ 428 'password' in module.params and module.params['password'] is not None 429 430 if not legacy_mode: 431 if module._socket_path: 432 connection = Connection(module._socket_path) 433 fos = FortiOSHandler(connection) 434 435 is_error, has_changed, result = fortios_dlp(module.params, fos) 436 else: 437 module.fail_json(**FAIL_SOCKET_MSG) 438 else: 439 try: 440 from fortiosapi import FortiOSAPI 441 except ImportError: 442 module.fail_json(msg="fortiosapi module is required") 443 444 fos = FortiOSAPI() 445 446 login(module.params, fos) 447 is_error, has_changed, result = fortios_dlp(module.params, fos) 448 fos.logout() 449 450 if not is_error: 451 module.exit_json(changed=has_changed, meta=result) 452 else: 453 module.fail_json(msg="Error in repo", meta=result) 454 455 456if __name__ == '__main__': 457 main() 458