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_threat_weight
27short_description: Configure threat weight settings 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 feature and threat_weight 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_threat_weight:
77        description:
78            - Configure threat weight settings.
79        default: null
80        type: dict
81        suboptions:
82            application:
83                description:
84                    - Application-control threat weight settings.
85                type: list
86                suboptions:
87                    category:
88                        description:
89                            - Application category.
90                        type: int
91                    id:
92                        description:
93                            - Entry ID.
94                        required: true
95                        type: int
96                    level:
97                        description:
98                            - Threat weight score for Application events.
99                        type: str
100                        choices:
101                            - disable
102                            - low
103                            - medium
104                            - high
105                            - critical
106            blocked_connection:
107                description:
108                    - Threat weight score for blocked connections.
109                type: str
110                choices:
111                    - disable
112                    - low
113                    - medium
114                    - high
115                    - critical
116            failed_connection:
117                description:
118                    - Threat weight score for failed connections.
119                type: str
120                choices:
121                    - disable
122                    - low
123                    - medium
124                    - high
125                    - critical
126            geolocation:
127                description:
128                    - Geolocation-based threat weight settings.
129                type: list
130                suboptions:
131                    country:
132                        description:
133                            - Country code.
134                        type: str
135                    id:
136                        description:
137                            - Entry ID.
138                        required: true
139                        type: int
140                    level:
141                        description:
142                            - Threat weight score for Geolocation-based events.
143                        type: str
144                        choices:
145                            - disable
146                            - low
147                            - medium
148                            - high
149                            - critical
150            ips:
151                description:
152                    - IPS threat weight settings.
153                type: dict
154                suboptions:
155                    critical_severity:
156                        description:
157                            - Threat weight score for IPS critical severity events.
158                        type: str
159                        choices:
160                            - disable
161                            - low
162                            - medium
163                            - high
164                            - critical
165                    high_severity:
166                        description:
167                            - Threat weight score for IPS high severity events.
168                        type: str
169                        choices:
170                            - disable
171                            - low
172                            - medium
173                            - high
174                            - critical
175                    info_severity:
176                        description:
177                            - Threat weight score for IPS info severity events.
178                        type: str
179                        choices:
180                            - disable
181                            - low
182                            - medium
183                            - high
184                            - critical
185                    low_severity:
186                        description:
187                            - Threat weight score for IPS low severity events.
188                        type: str
189                        choices:
190                            - disable
191                            - low
192                            - medium
193                            - high
194                            - critical
195                    medium_severity:
196                        description:
197                            - Threat weight score for IPS medium severity events.
198                        type: str
199                        choices:
200                            - disable
201                            - low
202                            - medium
203                            - high
204                            - critical
205            level:
206                description:
207                    - Score mapping for threat weight levels.
208                type: dict
209                suboptions:
210                    critical:
211                        description:
212                            - Critical level score value (1 - 100).
213                        type: int
214                    high:
215                        description:
216                            - High level score value (1 - 100).
217                        type: int
218                    low:
219                        description:
220                            - Low level score value (1 - 100).
221                        type: int
222                    medium:
223                        description:
224                            - Medium level score value (1 - 100).
225                        type: int
226            malware:
227                description:
228                    - Anti-virus malware threat weight settings.
229                type: dict
230                suboptions:
231                    botnet_connection:
232                        description:
233                            - Threat weight score for detected botnet connections.
234                        type: str
235                        choices:
236                            - disable
237                            - low
238                            - medium
239                            - high
240                            - critical
241                    command_blocked:
242                        description:
243                            - Threat weight score for blocked command detected.
244                        type: str
245                        choices:
246                            - disable
247                            - low
248                            - medium
249                            - high
250                            - critical
251                    content_disarm:
252                        description:
253                            - Threat weight score for virus (content disarm) detected.
254                        type: str
255                        choices:
256                            - disable
257                            - low
258                            - medium
259                            - high
260                            - critical
261                    mimefragmented:
262                        description:
263                            - Threat weight score for mimefragmented detected.
264                        type: str
265                        choices:
266                            - disable
267                            - low
268                            - medium
269                            - high
270                            - critical
271                    oversized:
272                        description:
273                            - Threat weight score for oversized file detected.
274                        type: str
275                        choices:
276                            - disable
277                            - low
278                            - medium
279                            - high
280                            - critical
281                    switch_proto:
282                        description:
283                            - Threat weight score for switch proto detected.
284                        type: str
285                        choices:
286                            - disable
287                            - low
288                            - medium
289                            - high
290                            - critical
291                    virus_blocked:
292                        description:
293                            - Threat weight score for virus (blocked) detected.
294                        type: str
295                        choices:
296                            - disable
297                            - low
298                            - medium
299                            - high
300                            - critical
301                    virus_file_type_executable:
302                        description:
303                            - Threat weight score for virus (filetype executable) detected.
304                        type: str
305                        choices:
306                            - disable
307                            - low
308                            - medium
309                            - high
310                            - critical
311                    virus_infected:
312                        description:
313                            - Threat weight score for virus (infected) detected.
314                        type: str
315                        choices:
316                            - disable
317                            - low
318                            - medium
319                            - high
320                            - critical
321                    virus_outbreak_prevention:
322                        description:
323                            - Threat weight score for virus (outbreak prevention) event.
324                        type: str
325                        choices:
326                            - disable
327                            - low
328                            - medium
329                            - high
330                            - critical
331                    virus_scan_error:
332                        description:
333                            - Threat weight score for virus (scan error) detected.
334                        type: str
335                        choices:
336                            - disable
337                            - low
338                            - medium
339                            - high
340                            - critical
341            status:
342                description:
343                    - Enable/disable the threat weight feature.
344                type: str
345                choices:
346                    - enable
347                    - disable
348            url_block_detected:
349                description:
350                    - Threat weight score for URL blocking.
351                type: str
352                choices:
353                    - disable
354                    - low
355                    - medium
356                    - high
357                    - critical
358            web:
359                description:
360                    - Web filtering threat weight settings.
361                type: list
362                suboptions:
363                    category:
364                        description:
365                            - Threat weight score for web category filtering matches.
366                        type: int
367                    id:
368                        description:
369                            - Entry ID.
370                        required: true
371                        type: int
372                    level:
373                        description:
374                            - Threat weight score for web category filtering matches.
375                        type: str
376                        choices:
377                            - disable
378                            - low
379                            - medium
380                            - high
381                            - critical
382'''
383
384EXAMPLES = '''
385- hosts: localhost
386  vars:
387   host: "192.168.122.40"
388   username: "admin"
389   password: ""
390   vdom: "root"
391   ssl_verify: "False"
392  tasks:
393  - name: Configure threat weight settings.
394    fortios_log_threat_weight:
395      host:  "{{ host }}"
396      username: "{{ username }}"
397      password: "{{ password }}"
398      vdom:  "{{ vdom }}"
399      https: "False"
400      log_threat_weight:
401        application:
402         -
403            category: "4"
404            id:  "5"
405            level: "disable"
406        blocked_connection: "disable"
407        failed_connection: "disable"
408        geolocation:
409         -
410            country: "<your_own_value>"
411            id:  "11"
412            level: "disable"
413        ips:
414            critical_severity: "disable"
415            high_severity: "disable"
416            info_severity: "disable"
417            low_severity: "disable"
418            medium_severity: "disable"
419        level:
420            critical: "20"
421            high: "21"
422            low: "22"
423            medium: "23"
424        malware:
425            botnet_connection: "disable"
426            command_blocked: "disable"
427            content_disarm: "disable"
428            mimefragmented: "disable"
429            oversized: "disable"
430            switch_proto: "disable"
431            virus_blocked: "disable"
432            virus_file_type_executable: "disable"
433            virus_infected: "disable"
434            virus_outbreak_prevention: "disable"
435            virus_scan_error: "disable"
436        status: "enable"
437        url_block_detected: "disable"
438        web:
439         -
440            category: "39"
441            id:  "40"
442            level: "disable"
443'''
444
445RETURN = '''
446build:
447  description: Build number of the fortigate image
448  returned: always
449  type: str
450  sample: '1547'
451http_method:
452  description: Last method used to provision the content into FortiGate
453  returned: always
454  type: str
455  sample: 'PUT'
456http_status:
457  description: Last result given by FortiGate on last operation applied
458  returned: always
459  type: str
460  sample: "200"
461mkey:
462  description: Master key (id) used in the last call to FortiGate
463  returned: success
464  type: str
465  sample: "id"
466name:
467  description: Name of the table used to fulfill the request
468  returned: always
469  type: str
470  sample: "urlfilter"
471path:
472  description: Path of the table used to fulfill the request
473  returned: always
474  type: str
475  sample: "webfilter"
476revision:
477  description: Internal revision number
478  returned: always
479  type: str
480  sample: "17.0.2.10658"
481serial:
482  description: Serial number of the unit
483  returned: always
484  type: str
485  sample: "FGVMEVYYQT3AB5352"
486status:
487  description: Indication of the operation's result
488  returned: always
489  type: str
490  sample: "success"
491vdom:
492  description: Virtual domain used
493  returned: always
494  type: str
495  sample: "root"
496version:
497  description: Version of the FortiGate
498  returned: always
499  type: str
500  sample: "v5.6.3"
501
502'''
503
504from ansible.module_utils.basic import AnsibleModule
505from ansible.module_utils.connection import Connection
506from ansible.module_utils.network.fortios.fortios import FortiOSHandler
507from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
508
509
510def login(data, fos):
511    host = data['host']
512    username = data['username']
513    password = data['password']
514    ssl_verify = data['ssl_verify']
515
516    fos.debug('on')
517    if 'https' in data and not data['https']:
518        fos.https('off')
519    else:
520        fos.https('on')
521
522    fos.login(host, username, password, verify=ssl_verify)
523
524
525def filter_log_threat_weight_data(json):
526    option_list = ['application', 'blocked_connection', 'failed_connection',
527                   'geolocation', 'ips', 'level',
528                   'malware', 'status', 'url_block_detected',
529                   'web']
530    dictionary = {}
531
532    for attribute in option_list:
533        if attribute in json and json[attribute] is not None:
534            dictionary[attribute] = json[attribute]
535
536    return dictionary
537
538
539def underscore_to_hyphen(data):
540    if isinstance(data, list):
541        for elem in data:
542            elem = underscore_to_hyphen(elem)
543    elif isinstance(data, dict):
544        new_data = {}
545        for k, v in data.items():
546            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
547        data = new_data
548
549    return data
550
551
552def log_threat_weight(data, fos):
553    vdom = data['vdom']
554    log_threat_weight_data = data['log_threat_weight']
555    filtered_data = underscore_to_hyphen(filter_log_threat_weight_data(log_threat_weight_data))
556
557    return fos.set('log',
558                   'threat-weight',
559                   data=filtered_data,
560                   vdom=vdom)
561
562
563def is_successful_status(status):
564    return status['status'] == "success" or \
565        status['http_method'] == "DELETE" and status['http_status'] == 404
566
567
568def fortios_log(data, fos):
569
570    if data['log_threat_weight']:
571        resp = log_threat_weight(data, fos)
572
573    return not is_successful_status(resp), \
574        resp['status'] == "success", \
575        resp
576
577
578def main():
579    fields = {
580        "host": {"required": False, "type": "str"},
581        "username": {"required": False, "type": "str"},
582        "password": {"required": False, "type": "str", "default": "", "no_log": True},
583        "vdom": {"required": False, "type": "str", "default": "root"},
584        "https": {"required": False, "type": "bool", "default": True},
585        "ssl_verify": {"required": False, "type": "bool", "default": True},
586        "log_threat_weight": {
587            "required": False, "type": "dict", "default": None,
588            "options": {
589                "application": {"required": False, "type": "list",
590                                "options": {
591                                    "category": {"required": False, "type": "int"},
592                                    "id": {"required": True, "type": "int"},
593                                    "level": {"required": False, "type": "str",
594                                              "choices": ["disable", "low", "medium",
595                                                          "high", "critical"]}
596                                }},
597                "blocked_connection": {"required": False, "type": "str",
598                                       "choices": ["disable", "low", "medium",
599                                                   "high", "critical"]},
600                "failed_connection": {"required": False, "type": "str",
601                                      "choices": ["disable", "low", "medium",
602                                                  "high", "critical"]},
603                "geolocation": {"required": False, "type": "list",
604                                "options": {
605                                    "country": {"required": False, "type": "str"},
606                                    "id": {"required": True, "type": "int"},
607                                    "level": {"required": False, "type": "str",
608                                              "choices": ["disable", "low", "medium",
609                                                          "high", "critical"]}
610                                }},
611                "ips": {"required": False, "type": "dict",
612                        "options": {
613                            "critical_severity": {"required": False, "type": "str",
614                                                  "choices": ["disable", "low", "medium",
615                                                              "high", "critical"]},
616                            "high_severity": {"required": False, "type": "str",
617                                              "choices": ["disable", "low", "medium",
618                                                          "high", "critical"]},
619                            "info_severity": {"required": False, "type": "str",
620                                              "choices": ["disable", "low", "medium",
621                                                          "high", "critical"]},
622                            "low_severity": {"required": False, "type": "str",
623                                             "choices": ["disable", "low", "medium",
624                                                         "high", "critical"]},
625                            "medium_severity": {"required": False, "type": "str",
626                                                "choices": ["disable", "low", "medium",
627                                                            "high", "critical"]}
628                        }},
629                "level": {"required": False, "type": "dict",
630                          "options": {
631                              "critical": {"required": False, "type": "int"},
632                              "high": {"required": False, "type": "int"},
633                              "low": {"required": False, "type": "int"},
634                              "medium": {"required": False, "type": "int"}
635                          }},
636                "malware": {"required": False, "type": "dict",
637                            "options": {
638                                "botnet_connection": {"required": False, "type": "str",
639                                                      "choices": ["disable", "low", "medium",
640                                                                  "high", "critical"]},
641                                "command_blocked": {"required": False, "type": "str",
642                                                    "choices": ["disable", "low", "medium",
643                                                                "high", "critical"]},
644                                "content_disarm": {"required": False, "type": "str",
645                                                   "choices": ["disable", "low", "medium",
646                                                               "high", "critical"]},
647                                "mimefragmented": {"required": False, "type": "str",
648                                                   "choices": ["disable", "low", "medium",
649                                                               "high", "critical"]},
650                                "oversized": {"required": False, "type": "str",
651                                              "choices": ["disable", "low", "medium",
652                                                          "high", "critical"]},
653                                "switch_proto": {"required": False, "type": "str",
654                                                 "choices": ["disable", "low", "medium",
655                                                             "high", "critical"]},
656                                "virus_blocked": {"required": False, "type": "str",
657                                                  "choices": ["disable", "low", "medium",
658                                                              "high", "critical"]},
659                                "virus_file_type_executable": {"required": False, "type": "str",
660                                                               "choices": ["disable", "low", "medium",
661                                                                           "high", "critical"]},
662                                "virus_infected": {"required": False, "type": "str",
663                                                   "choices": ["disable", "low", "medium",
664                                                               "high", "critical"]},
665                                "virus_outbreak_prevention": {"required": False, "type": "str",
666                                                              "choices": ["disable", "low", "medium",
667                                                                          "high", "critical"]},
668                                "virus_scan_error": {"required": False, "type": "str",
669                                                     "choices": ["disable", "low", "medium",
670                                                                 "high", "critical"]}
671                            }},
672                "status": {"required": False, "type": "str",
673                           "choices": ["enable", "disable"]},
674                "url_block_detected": {"required": False, "type": "str",
675                                       "choices": ["disable", "low", "medium",
676                                                   "high", "critical"]},
677                "web": {"required": False, "type": "list",
678                        "options": {
679                            "category": {"required": False, "type": "int"},
680                            "id": {"required": True, "type": "int"},
681                            "level": {"required": False, "type": "str",
682                                      "choices": ["disable", "low", "medium",
683                                                  "high", "critical"]}
684                        }}
685
686            }
687        }
688    }
689
690    module = AnsibleModule(argument_spec=fields,
691                           supports_check_mode=False)
692
693    # legacy_mode refers to using fortiosapi instead of HTTPAPI
694    legacy_mode = 'host' in module.params and module.params['host'] is not None and \
695                  'username' in module.params and module.params['username'] is not None and \
696                  'password' in module.params and module.params['password'] is not None
697
698    if not legacy_mode:
699        if module._socket_path:
700            connection = Connection(module._socket_path)
701            fos = FortiOSHandler(connection)
702
703            is_error, has_changed, result = fortios_log(module.params, fos)
704        else:
705            module.fail_json(**FAIL_SOCKET_MSG)
706    else:
707        try:
708            from fortiosapi import FortiOSAPI
709        except ImportError:
710            module.fail_json(msg="fortiosapi module is required")
711
712        fos = FortiOSAPI()
713
714        login(module.params, fos)
715        is_error, has_changed, result = fortios_log(module.params, fos)
716        fos.logout()
717
718    if not is_error:
719        module.exit_json(changed=has_changed, meta=result)
720    else:
721        module.fail_json(msg="Error in repo", meta=result)
722
723
724if __name__ == '__main__':
725    main()
726