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