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