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