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_log_fortiguard_override_filter
27short_description: Override filters for FortiCloud 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 log_fortiguard feature and override_filter 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    log_fortiguard_override_filter:
77        description:
78            - Override filters for FortiCloud.
79        default: null
80        type: dict
81        suboptions:
82            anomaly:
83                description:
84                    - Enable/disable anomaly logging.
85                type: str
86                choices:
87                    - enable
88                    - disable
89            dlp_archive:
90                description:
91                    - Enable/disable DLP archive logging.
92                type: str
93                choices:
94                    - enable
95                    - disable
96            dns:
97                description:
98                    - Enable/disable detailed DNS event logging.
99                type: str
100                choices:
101                    - enable
102                    - disable
103            filter:
104                description:
105                    - FortiCloud log filter.
106                type: str
107            filter_type:
108                description:
109                    - Include/exclude logs that match the filter.
110                type: str
111                choices:
112                    - include
113                    - exclude
114            forward_traffic:
115                description:
116                    - Enable/disable forward traffic logging.
117                type: str
118                choices:
119                    - enable
120                    - disable
121            gtp:
122                description:
123                    - Enable/disable GTP messages logging.
124                type: str
125                choices:
126                    - enable
127                    - disable
128            local_traffic:
129                description:
130                    - Enable/disable local in or out traffic logging.
131                type: str
132                choices:
133                    - enable
134                    - disable
135            multicast_traffic:
136                description:
137                    - Enable/disable multicast traffic logging.
138                type: str
139                choices:
140                    - enable
141                    - disable
142            netscan_discovery:
143                description:
144                    - Enable/disable netscan discovery event logging.
145                type: str
146            netscan_vulnerability:
147                description:
148                    - Enable/disable netscan vulnerability event logging.
149                type: str
150            severity:
151                description:
152                    - Lowest severity level to log.
153                type: str
154                choices:
155                    - emergency
156                    - alert
157                    - critical
158                    - error
159                    - warning
160                    - notification
161                    - information
162                    - debug
163            sniffer_traffic:
164                description:
165                    - Enable/disable sniffer traffic logging.
166                type: str
167                choices:
168                    - enable
169                    - disable
170            ssh:
171                description:
172                    - Enable/disable SSH logging.
173                type: str
174                choices:
175                    - enable
176                    - disable
177            voip:
178                description:
179                    - Enable/disable VoIP logging.
180                type: str
181                choices:
182                    - enable
183                    - disable
184'''
185
186EXAMPLES = '''
187- hosts: localhost
188  vars:
189   host: "192.168.122.40"
190   username: "admin"
191   password: ""
192   vdom: "root"
193   ssl_verify: "False"
194  tasks:
195  - name: Override filters for FortiCloud.
196    fortios_log_fortiguard_override_filter:
197      host:  "{{ host }}"
198      username: "{{ username }}"
199      password: "{{ password }}"
200      vdom:  "{{ vdom }}"
201      https: "False"
202      log_fortiguard_override_filter:
203        anomaly: "enable"
204        dlp_archive: "enable"
205        dns: "enable"
206        filter: "<your_own_value>"
207        filter_type: "include"
208        forward_traffic: "enable"
209        gtp: "enable"
210        local_traffic: "enable"
211        multicast_traffic: "enable"
212        netscan_discovery: "<your_own_value>"
213        netscan_vulnerability: "<your_own_value>"
214        severity: "emergency"
215        sniffer_traffic: "enable"
216        ssh: "enable"
217        voip: "enable"
218'''
219
220RETURN = '''
221build:
222  description: Build number of the fortigate image
223  returned: always
224  type: str
225  sample: '1547'
226http_method:
227  description: Last method used to provision the content into FortiGate
228  returned: always
229  type: str
230  sample: 'PUT'
231http_status:
232  description: Last result given by FortiGate on last operation applied
233  returned: always
234  type: str
235  sample: "200"
236mkey:
237  description: Master key (id) used in the last call to FortiGate
238  returned: success
239  type: str
240  sample: "id"
241name:
242  description: Name of the table used to fulfill the request
243  returned: always
244  type: str
245  sample: "urlfilter"
246path:
247  description: Path of the table used to fulfill the request
248  returned: always
249  type: str
250  sample: "webfilter"
251revision:
252  description: Internal revision number
253  returned: always
254  type: str
255  sample: "17.0.2.10658"
256serial:
257  description: Serial number of the unit
258  returned: always
259  type: str
260  sample: "FGVMEVYYQT3AB5352"
261status:
262  description: Indication of the operation's result
263  returned: always
264  type: str
265  sample: "success"
266vdom:
267  description: Virtual domain used
268  returned: always
269  type: str
270  sample: "root"
271version:
272  description: Version of the FortiGate
273  returned: always
274  type: str
275  sample: "v5.6.3"
276
277'''
278
279from ansible.module_utils.basic import AnsibleModule
280from ansible.module_utils.connection import Connection
281from ansible.module_utils.network.fortios.fortios import FortiOSHandler
282from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
283
284
285def login(data, fos):
286    host = data['host']
287    username = data['username']
288    password = data['password']
289    ssl_verify = data['ssl_verify']
290
291    fos.debug('on')
292    if 'https' in data and not data['https']:
293        fos.https('off')
294    else:
295        fos.https('on')
296
297    fos.login(host, username, password, verify=ssl_verify)
298
299
300def filter_log_fortiguard_override_filter_data(json):
301    option_list = ['anomaly', 'dlp_archive', 'dns',
302                   'filter', 'filter_type', 'forward_traffic',
303                   'gtp', 'local_traffic', 'multicast_traffic',
304                   'netscan_discovery', 'netscan_vulnerability', 'severity',
305                   'sniffer_traffic', 'ssh', 'voip']
306    dictionary = {}
307
308    for attribute in option_list:
309        if attribute in json and json[attribute] is not None:
310            dictionary[attribute] = json[attribute]
311
312    return dictionary
313
314
315def underscore_to_hyphen(data):
316    if isinstance(data, list):
317        for elem in data:
318            elem = underscore_to_hyphen(elem)
319    elif isinstance(data, dict):
320        new_data = {}
321        for k, v in data.items():
322            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
323        data = new_data
324
325    return data
326
327
328def log_fortiguard_override_filter(data, fos):
329    vdom = data['vdom']
330    log_fortiguard_override_filter_data = data['log_fortiguard_override_filter']
331    filtered_data = underscore_to_hyphen(filter_log_fortiguard_override_filter_data(log_fortiguard_override_filter_data))
332
333    return fos.set('log.fortiguard',
334                   'override-filter',
335                   data=filtered_data,
336                   vdom=vdom)
337
338
339def is_successful_status(status):
340    return status['status'] == "success" or \
341        status['http_method'] == "DELETE" and status['http_status'] == 404
342
343
344def fortios_log_fortiguard(data, fos):
345
346    if data['log_fortiguard_override_filter']:
347        resp = log_fortiguard_override_filter(data, fos)
348
349    return not is_successful_status(resp), \
350        resp['status'] == "success", \
351        resp
352
353
354def main():
355    fields = {
356        "host": {"required": False, "type": "str"},
357        "username": {"required": False, "type": "str"},
358        "password": {"required": False, "type": "str", "default": "", "no_log": True},
359        "vdom": {"required": False, "type": "str", "default": "root"},
360        "https": {"required": False, "type": "bool", "default": True},
361        "ssl_verify": {"required": False, "type": "bool", "default": True},
362        "log_fortiguard_override_filter": {
363            "required": False, "type": "dict", "default": None,
364            "options": {
365                "anomaly": {"required": False, "type": "str",
366                            "choices": ["enable", "disable"]},
367                "dlp_archive": {"required": False, "type": "str",
368                                "choices": ["enable", "disable"]},
369                "dns": {"required": False, "type": "str",
370                        "choices": ["enable", "disable"]},
371                "filter": {"required": False, "type": "str"},
372                "filter_type": {"required": False, "type": "str",
373                                "choices": ["include", "exclude"]},
374                "forward_traffic": {"required": False, "type": "str",
375                                    "choices": ["enable", "disable"]},
376                "gtp": {"required": False, "type": "str",
377                        "choices": ["enable", "disable"]},
378                "local_traffic": {"required": False, "type": "str",
379                                  "choices": ["enable", "disable"]},
380                "multicast_traffic": {"required": False, "type": "str",
381                                      "choices": ["enable", "disable"]},
382                "netscan_discovery": {"required": False, "type": "str"},
383                "netscan_vulnerability": {"required": False, "type": "str"},
384                "severity": {"required": False, "type": "str",
385                             "choices": ["emergency", "alert", "critical",
386                                         "error", "warning", "notification",
387                                         "information", "debug"]},
388                "sniffer_traffic": {"required": False, "type": "str",
389                                    "choices": ["enable", "disable"]},
390                "ssh": {"required": False, "type": "str",
391                        "choices": ["enable", "disable"]},
392                "voip": {"required": False, "type": "str",
393                         "choices": ["enable", "disable"]}
394
395            }
396        }
397    }
398
399    module = AnsibleModule(argument_spec=fields,
400                           supports_check_mode=False)
401
402    # legacy_mode refers to using fortiosapi instead of HTTPAPI
403    legacy_mode = 'host' in module.params and module.params['host'] is not None and \
404                  'username' in module.params and module.params['username'] is not None and \
405                  'password' in module.params and module.params['password'] is not None
406
407    if not legacy_mode:
408        if module._socket_path:
409            connection = Connection(module._socket_path)
410            fos = FortiOSHandler(connection)
411
412            is_error, has_changed, result = fortios_log_fortiguard(module.params, fos)
413        else:
414            module.fail_json(**FAIL_SOCKET_MSG)
415    else:
416        try:
417            from fortiosapi import FortiOSAPI
418        except ImportError:
419            module.fail_json(msg="fortiosapi module is required")
420
421        fos = FortiOSAPI()
422
423        login(module.params, fos)
424        is_error, has_changed, result = fortios_log_fortiguard(module.params, fos)
425        fos.logout()
426
427    if not is_error:
428        module.exit_json(changed=has_changed, meta=result)
429    else:
430        module.fail_json(msg="Error in repo", meta=result)
431
432
433if __name__ == '__main__':
434    main()
435