1#!/usr/local/bin/python3.8
2from __future__ import (absolute_import, division, print_function)
3# Copyright 2019-2020 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_spamfilter_profile
27short_description: Configure AntiSpam profiles 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 spamfilter feature and profile category.
31      Examples include all parameters and values need to be adjusted to datasources before usage.
32      Tested with FOS v6.0.0
33version_added: "2.10"
34author:
35    - Link Zheng (@chillancezen)
36    - Jie Xue (@JieX19)
37    - Hongbin Lu (@fgtdev-hblu)
38    - Frank Shen (@frankshen01)
39    - Miguel Angel Munoz (@mamunozgonzalez)
40    - Nicolas Thomas (@thomnico)
41notes:
42    - Legacy fortiosapi has been deprecated, httpapi is the preferred way to run playbooks
43
44requirements:
45    - ansible>=2.9.0
46options:
47    access_token:
48        description:
49            - Token-based authentication.
50              Generated from GUI of Fortigate.
51        type: str
52        required: false
53    enable_log:
54        description:
55            - Enable/Disable logging for task.
56        type: bool
57        required: false
58        default: false
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
67    state:
68        description:
69            - Indicates whether to create or remove the object.
70        type: str
71        required: true
72        choices:
73            - present
74            - absent
75    spamfilter_profile:
76        description:
77            - Configure AntiSpam profiles.
78        default: null
79        type: dict
80        suboptions:
81            comment:
82                description:
83                    - Comment.
84                type: str
85            external:
86                description:
87                    - Enable/disable external Email inspection.
88                type: str
89                choices:
90                    - enable
91                    - disable
92            flow_based:
93                description:
94                    - Enable/disable flow-based spam filtering.
95                type: str
96                choices:
97                    - enable
98                    - disable
99            gmail:
100                description:
101                    - Gmail.
102                type: dict
103                suboptions:
104                    log:
105                        description:
106                            - Enable/disable logging.
107                        type: str
108                        choices:
109                            - enable
110                            - disable
111            imap:
112                description:
113                    - IMAP.
114                type: dict
115                suboptions:
116                    action:
117                        description:
118                            - Action for spam email.
119                        type: str
120                        choices:
121                            - pass
122                            - tag
123                    log:
124                        description:
125                            - Enable/disable logging.
126                        type: str
127                        choices:
128                            - enable
129                            - disable
130                    tag_msg:
131                        description:
132                            - Subject text or header added to spam email.
133                        type: str
134                    tag_type:
135                        description:
136                            - Tag subject or header for spam email.
137                        type: list
138                        choices:
139                            - subject
140                            - header
141                            - spaminfo
142            mapi:
143                description:
144                    - MAPI.
145                type: dict
146                suboptions:
147                    action:
148                        description:
149                            - Action for spam email.
150                        type: str
151                        choices:
152                            - pass
153                            - discard
154                    log:
155                        description:
156                            - Enable/disable logging.
157                        type: str
158                        choices:
159                            - enable
160                            - disable
161            msn_hotmail:
162                description:
163                    - MSN Hotmail.
164                type: dict
165                suboptions:
166                    log:
167                        description:
168                            - Enable/disable logging.
169                        type: str
170                        choices:
171                            - enable
172                            - disable
173            name:
174                description:
175                    - Profile name.
176                required: true
177                type: str
178            options:
179                description:
180                    - Options.
181                type: list
182                choices:
183                    - bannedword
184                    - spambwl
185                    - spamfsip
186                    - spamfssubmit
187                    - spamfschksum
188                    - spamfsurl
189                    - spamhelodns
190                    - spamraddrdns
191                    - spamrbl
192                    - spamhdrcheck
193                    - spamfsphish
194            pop3:
195                description:
196                    - POP3.
197                type: dict
198                suboptions:
199                    action:
200                        description:
201                            - Action for spam email.
202                        type: str
203                        choices:
204                            - pass
205                            - tag
206                    log:
207                        description:
208                            - Enable/disable logging.
209                        type: str
210                        choices:
211                            - enable
212                            - disable
213                    tag_msg:
214                        description:
215                            - Subject text or header added to spam email.
216                        type: str
217                    tag_type:
218                        description:
219                            - Tag subject or header for spam email.
220                        type: list
221                        choices:
222                            - subject
223                            - header
224                            - spaminfo
225            replacemsg_group:
226                description:
227                    - Replacement message group. Source system.replacemsg-group.name.
228                type: str
229            smtp:
230                description:
231                    - SMTP.
232                type: dict
233                suboptions:
234                    action:
235                        description:
236                            - Action for spam email.
237                        type: str
238                        choices:
239                            - pass
240                            - tag
241                            - discard
242                    hdrip:
243                        description:
244                            - Enable/disable SMTP email header IP checks for spamfsip, spamrbl and spambwl filters.
245                        type: str
246                        choices:
247                            - disable
248                            - enable
249                    local_override:
250                        description:
251                            - Enable/disable local filter to override SMTP remote check result.
252                        type: str
253                        choices:
254                            - disable
255                            - enable
256                    log:
257                        description:
258                            - Enable/disable logging.
259                        type: str
260                        choices:
261                            - enable
262                            - disable
263                    tag_msg:
264                        description:
265                            - Subject text or header added to spam email.
266                        type: str
267                    tag_type:
268                        description:
269                            - Tag subject or header for spam email.
270                        type: list
271                        choices:
272                            - subject
273                            - header
274                            - spaminfo
275            spam_bwl_table:
276                description:
277                    - Anti-spam black/white list table ID. Source spamfilter.bwl.id.
278                type: int
279            spam_bword_table:
280                description:
281                    - Anti-spam banned word table ID. Source spamfilter.bword.id.
282                type: int
283            spam_bword_threshold:
284                description:
285                    - Spam banned word threshold.
286                type: int
287            spam_filtering:
288                description:
289                    - Enable/disable spam filtering.
290                type: str
291                choices:
292                    - enable
293                    - disable
294            spam_iptrust_table:
295                description:
296                    - Anti-spam IP trust table ID. Source spamfilter.iptrust.id.
297                type: int
298            spam_log:
299                description:
300                    - Enable/disable spam logging for email filtering.
301                type: str
302                choices:
303                    - disable
304                    - enable
305            spam_log_fortiguard_response:
306                description:
307                    - Enable/disable logging FortiGuard spam response.
308                type: str
309                choices:
310                    - disable
311                    - enable
312            spam_mheader_table:
313                description:
314                    - Anti-spam MIME header table ID. Source spamfilter.mheader.id.
315                type: int
316            spam_rbl_table:
317                description:
318                    - Anti-spam DNSBL table ID. Source spamfilter.dnsbl.id.
319                type: int
320            yahoo_mail:
321                description:
322                    - Yahoo! Mail.
323                type: dict
324                suboptions:
325                    log:
326                        description:
327                            - Enable/disable logging.
328                        type: str
329                        choices:
330                            - enable
331                            - disable
332'''
333
334EXAMPLES = '''
335- hosts: fortigates
336  collections:
337    - fortinet.fortios
338  connection: httpapi
339  vars:
340   vdom: "root"
341   ansible_httpapi_use_ssl: yes
342   ansible_httpapi_validate_certs: no
343   ansible_httpapi_port: 443
344  tasks:
345  - name: Configure AntiSpam profiles.
346    fortios_spamfilter_profile:
347      vdom:  "{{ vdom }}"
348      state: "present"
349      access_token: "<your_own_value>"
350      spamfilter_profile:
351        comment: "Comment."
352        external: "enable"
353        flow_based: "enable"
354        gmail:
355            log: "enable"
356        imap:
357            action: "pass"
358            log: "enable"
359            tag_msg: "<your_own_value>"
360            tag_type: "subject"
361        mapi:
362            action: "pass"
363            log: "enable"
364        msn_hotmail:
365            log: "enable"
366        name: "default_name_18"
367        options: "bannedword"
368        pop3:
369            action: "pass"
370            log: "enable"
371            tag_msg: "<your_own_value>"
372            tag_type: "subject"
373        replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)"
374        smtp:
375            action: "pass"
376            hdrip: "disable"
377            local_override: "disable"
378            log: "enable"
379            tag_msg: "<your_own_value>"
380            tag_type: "subject"
381        spam_bwl_table: "33 (source spamfilter.bwl.id)"
382        spam_bword_table: "34 (source spamfilter.bword.id)"
383        spam_bword_threshold: "35"
384        spam_filtering: "enable"
385        spam_iptrust_table: "37 (source spamfilter.iptrust.id)"
386        spam_log: "disable"
387        spam_log_fortiguard_response: "disable"
388        spam_mheader_table: "40 (source spamfilter.mheader.id)"
389        spam_rbl_table: "41 (source spamfilter.dnsbl.id)"
390        yahoo_mail:
391            log: "enable"
392
393'''
394
395RETURN = '''
396build:
397  description: Build number of the fortigate image
398  returned: always
399  type: str
400  sample: '1547'
401http_method:
402  description: Last method used to provision the content into FortiGate
403  returned: always
404  type: str
405  sample: 'PUT'
406http_status:
407  description: Last result given by FortiGate on last operation applied
408  returned: always
409  type: str
410  sample: "200"
411mkey:
412  description: Master key (id) used in the last call to FortiGate
413  returned: success
414  type: str
415  sample: "id"
416name:
417  description: Name of the table used to fulfill the request
418  returned: always
419  type: str
420  sample: "urlfilter"
421path:
422  description: Path of the table used to fulfill the request
423  returned: always
424  type: str
425  sample: "webfilter"
426revision:
427  description: Internal revision number
428  returned: always
429  type: str
430  sample: "17.0.2.10658"
431serial:
432  description: Serial number of the unit
433  returned: always
434  type: str
435  sample: "FGVMEVYYQT3AB5352"
436status:
437  description: Indication of the operation's result
438  returned: always
439  type: str
440  sample: "success"
441vdom:
442  description: Virtual domain used
443  returned: always
444  type: str
445  sample: "root"
446version:
447  description: Version of the FortiGate
448  returned: always
449  type: str
450  sample: "v5.6.3"
451
452'''
453from ansible.module_utils.basic import AnsibleModule
454from ansible.module_utils.connection import Connection
455from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
456from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
457from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
458from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
459from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
460from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
461from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize
462
463
464def filter_spamfilter_profile_data(json):
465    option_list = ['comment', 'external', 'flow_based',
466                   'gmail', 'imap', 'mapi',
467                   'msn_hotmail', 'name', 'options',
468                   'pop3', 'replacemsg_group', 'smtp',
469                   'spam_bwl_table', 'spam_bword_table', 'spam_bword_threshold',
470                   'spam_filtering', 'spam_iptrust_table', 'spam_log',
471                   'spam_log_fortiguard_response', 'spam_mheader_table', 'spam_rbl_table',
472                   'yahoo_mail']
473    dictionary = {}
474
475    for attribute in option_list:
476        if attribute in json and json[attribute] is not None:
477            dictionary[attribute] = json[attribute]
478
479    return dictionary
480
481
482def flatten_single_path(data, path, index):
483    if not data or index == len(path) or path[index] not in data or not data[path[index]]:
484        return
485
486    if index == len(path) - 1:
487        data[path[index]] = ' '.join(str(elem) for elem in data[path[index]])
488    elif isinstance(data[path[index]], list):
489        for value in data[path[index]]:
490            flatten_single_path(value, path, index + 1)
491    else:
492        flatten_single_path(data[path[index]], path, index + 1)
493
494
495def flatten_multilists_attributes(data):
496    multilist_attrs = [[u'options'], [u'imap', u'tag_type'], [u'pop3', u'tag_type'], [u'smtp', u'tag_type']]
497
498    for attr in multilist_attrs:
499        flatten_single_path(data, attr, 0)
500
501    return data
502
503
504def underscore_to_hyphen(data):
505    if isinstance(data, list):
506        for i, elem in enumerate(data):
507            data[i] = underscore_to_hyphen(elem)
508    elif isinstance(data, dict):
509        new_data = {}
510        for k, v in data.items():
511            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
512        data = new_data
513
514    return data
515
516
517def spamfilter_profile(data, fos, check_mode=False):
518
519    vdom = data['vdom']
520
521    state = data['state']
522
523    spamfilter_profile_data = data['spamfilter_profile']
524    spamfilter_profile_data = flatten_multilists_attributes(spamfilter_profile_data)
525    filtered_data = underscore_to_hyphen(filter_spamfilter_profile_data(spamfilter_profile_data))
526
527    # check_mode starts from here
528    if check_mode:
529        mkey = fos.get_mkey('system', 'interface', filtered_data, vdom=vdom)
530        current_data = fos.get('system', 'interface', vdom=vdom, mkey=mkey)
531        is_existed = current_data and current_data.get('http_status') == 200 \
532            and isinstance(current_data.get('results'), list) \
533            and len(current_data['results']) > 0
534
535        # 2. if it exists and the state is 'present' then compare current settings with desired
536        if state == 'present' or state is True:
537            if mkey is None:
538                return False, True, filtered_data
539
540            # if mkey exists then compare each other
541            # record exits and they're matched or not
542            if is_existed:
543                is_same = is_same_comparison(
544                    serialize(current_data['results'][0]), serialize(filtered_data))
545                return False, not is_same, filtered_data
546
547            # record does not exist
548            return False, True, filtered_data
549
550        if state == 'absent':
551            if mkey is None:
552                return False, False, filtered_data
553
554            if is_existed:
555                return False, True, filtered_data
556            return False, False, filtered_data
557
558        return True, False, {'reason: ': 'Must provide state parameter'}
559
560    if state == "present" or state is True:
561        return fos.set('spamfilter',
562                       'profile',
563                       data=filtered_data,
564                       vdom=vdom)
565
566    elif state == "absent":
567        return fos.delete('spamfilter',
568                          'profile',
569                          mkey=filtered_data['name'],
570                          vdom=vdom)
571    else:
572        fos._module.fail_json(msg='state must be present or absent!')
573
574
575def is_successful_status(status):
576    return status['status'] == "success" or \
577        status['http_method'] == "DELETE" and status['http_status'] == 404
578
579
580def fortios_spamfilter(data, fos, check_mode):
581
582    if data['spamfilter_profile']:
583        resp = spamfilter_profile(data, fos, check_mode)
584    else:
585        fos._module.fail_json(msg='missing task body: %s' % ('spamfilter_profile'))
586    if check_mode:
587        return resp
588    return not is_successful_status(resp), \
589        resp['status'] == "success" and \
590        (resp['revision_changed'] if 'revision_changed' in resp else True), \
591        resp
592
593
594versioned_schema = {
595    "type": "list",
596    "children": {
597        "comment": {
598            "type": "string",
599            "revisions": {
600                "v6.0.11": True,
601                "v6.0.0": True,
602                "v6.0.5": True
603            }
604        },
605        "spam_bword_threshold": {
606            "type": "integer",
607            "revisions": {
608                "v6.0.11": True,
609                "v6.0.0": True,
610                "v6.0.5": True
611            }
612        },
613        "spam_iptrust_table": {
614            "type": "integer",
615            "revisions": {
616                "v6.0.11": True,
617                "v6.0.0": True,
618                "v6.0.5": True
619            }
620        },
621        "spam_log_fortiguard_response": {
622            "type": "string",
623            "options": [
624                {
625                    "value": "disable",
626                    "revisions": {
627                        "v6.0.11": True,
628                        "v6.0.0": True,
629                        "v6.0.5": True
630                    }
631                },
632                {
633                    "value": "enable",
634                    "revisions": {
635                        "v6.0.11": True,
636                        "v6.0.0": True,
637                        "v6.0.5": True
638                    }
639                }
640            ],
641            "revisions": {
642                "v6.0.11": True,
643                "v6.0.0": True,
644                "v6.0.5": True
645            }
646        },
647        "smtp": {
648            "type": "dict",
649            "children": {
650                "local_override": {
651                    "type": "string",
652                    "options": [
653                        {
654                            "value": "disable",
655                            "revisions": {
656                                "v6.0.11": True,
657                                "v6.0.0": True,
658                                "v6.0.5": True
659                            }
660                        },
661                        {
662                            "value": "enable",
663                            "revisions": {
664                                "v6.0.11": True,
665                                "v6.0.0": True,
666                                "v6.0.5": True
667                            }
668                        }
669                    ],
670                    "revisions": {
671                        "v6.0.11": True,
672                        "v6.0.0": True,
673                        "v6.0.5": True
674                    }
675                },
676                "hdrip": {
677                    "type": "string",
678                    "options": [
679                        {
680                            "value": "disable",
681                            "revisions": {
682                                "v6.0.11": True,
683                                "v6.0.0": True,
684                                "v6.0.5": True
685                            }
686                        },
687                        {
688                            "value": "enable",
689                            "revisions": {
690                                "v6.0.11": True,
691                                "v6.0.0": True,
692                                "v6.0.5": True
693                            }
694                        }
695                    ],
696                    "revisions": {
697                        "v6.0.11": True,
698                        "v6.0.0": True,
699                        "v6.0.5": True
700                    }
701                },
702                "log": {
703                    "type": "string",
704                    "options": [
705                        {
706                            "value": "enable",
707                            "revisions": {
708                                "v6.0.11": True,
709                                "v6.0.0": True,
710                                "v6.0.5": True
711                            }
712                        },
713                        {
714                            "value": "disable",
715                            "revisions": {
716                                "v6.0.11": True,
717                                "v6.0.0": True,
718                                "v6.0.5": True
719                            }
720                        }
721                    ],
722                    "revisions": {
723                        "v6.0.11": True,
724                        "v6.0.0": True,
725                        "v6.0.5": True
726                    }
727                },
728                "action": {
729                    "type": "string",
730                    "options": [
731                        {
732                            "value": "pass",
733                            "revisions": {
734                                "v6.0.11": True,
735                                "v6.0.0": True,
736                                "v6.0.5": True
737                            }
738                        },
739                        {
740                            "value": "tag",
741                            "revisions": {
742                                "v6.0.11": True,
743                                "v6.0.0": True,
744                                "v6.0.5": True
745                            }
746                        },
747                        {
748                            "value": "discard",
749                            "revisions": {
750                                "v6.0.11": True,
751                                "v6.0.0": True,
752                                "v6.0.5": True
753                            }
754                        }
755                    ],
756                    "revisions": {
757                        "v6.0.11": True,
758                        "v6.0.0": True,
759                        "v6.0.5": True
760                    }
761                },
762                "tag_msg": {
763                    "type": "string",
764                    "revisions": {
765                        "v6.0.11": True,
766                        "v6.0.0": True,
767                        "v6.0.5": True
768                    }
769                },
770                "tag_type": {
771                    "type": "list",
772                    "options": [
773                        {
774                            "value": "subject",
775                            "revisions": {
776                                "v6.0.11": True,
777                                "v6.0.0": True,
778                                "v6.0.5": True
779                            }
780                        },
781                        {
782                            "value": "header",
783                            "revisions": {
784                                "v6.0.11": True,
785                                "v6.0.0": True,
786                                "v6.0.5": True
787                            }
788                        },
789                        {
790                            "value": "spaminfo",
791                            "revisions": {
792                                "v6.0.11": True,
793                                "v6.0.0": True,
794                                "v6.0.5": True
795                            }
796                        }
797                    ],
798                    "revisions": {
799                        "v6.0.11": True,
800                        "v6.0.0": True,
801                        "v6.0.5": True
802                    }
803                }
804            },
805            "revisions": {
806                "v6.0.11": True,
807                "v6.0.0": True,
808                "v6.0.5": True
809            }
810        },
811        "replacemsg_group": {
812            "type": "string",
813            "revisions": {
814                "v6.0.11": True,
815                "v6.0.0": True,
816                "v6.0.5": True
817            }
818        },
819        "gmail": {
820            "type": "dict",
821            "children": {
822                "log": {
823                    "type": "string",
824                    "options": [
825                        {
826                            "value": "enable",
827                            "revisions": {
828                                "v6.0.11": True,
829                                "v6.0.0": True,
830                                "v6.0.5": True
831                            }
832                        },
833                        {
834                            "value": "disable",
835                            "revisions": {
836                                "v6.0.11": True,
837                                "v6.0.0": True,
838                                "v6.0.5": True
839                            }
840                        }
841                    ],
842                    "revisions": {
843                        "v6.0.11": True,
844                        "v6.0.0": True,
845                        "v6.0.5": True
846                    }
847                }
848            },
849            "revisions": {
850                "v6.0.11": True,
851                "v6.0.0": True,
852                "v6.0.5": True
853            }
854        },
855        "spam_mheader_table": {
856            "type": "integer",
857            "revisions": {
858                "v6.0.11": True,
859                "v6.0.0": True,
860                "v6.0.5": True
861            }
862        },
863        "spam_rbl_table": {
864            "type": "integer",
865            "revisions": {
866                "v6.0.11": True,
867                "v6.0.0": True,
868                "v6.0.5": True
869            }
870        },
871        "mapi": {
872            "type": "dict",
873            "children": {
874                "action": {
875                    "type": "string",
876                    "options": [
877                        {
878                            "value": "pass",
879                            "revisions": {
880                                "v6.0.11": True,
881                                "v6.0.0": True,
882                                "v6.0.5": True
883                            }
884                        },
885                        {
886                            "value": "discard",
887                            "revisions": {
888                                "v6.0.11": True,
889                                "v6.0.0": True,
890                                "v6.0.5": True
891                            }
892                        }
893                    ],
894                    "revisions": {
895                        "v6.0.11": True,
896                        "v6.0.0": True,
897                        "v6.0.5": True
898                    }
899                },
900                "log": {
901                    "type": "string",
902                    "options": [
903                        {
904                            "value": "enable",
905                            "revisions": {
906                                "v6.0.11": True,
907                                "v6.0.0": True,
908                                "v6.0.5": True
909                            }
910                        },
911                        {
912                            "value": "disable",
913                            "revisions": {
914                                "v6.0.11": True,
915                                "v6.0.0": True,
916                                "v6.0.5": True
917                            }
918                        }
919                    ],
920                    "revisions": {
921                        "v6.0.11": True,
922                        "v6.0.0": True,
923                        "v6.0.5": True
924                    }
925                }
926            },
927            "revisions": {
928                "v6.0.11": True,
929                "v6.0.0": True,
930                "v6.0.5": True
931            }
932        },
933        "spam_bword_table": {
934            "type": "integer",
935            "revisions": {
936                "v6.0.11": True,
937                "v6.0.0": True,
938                "v6.0.5": True
939            }
940        },
941        "yahoo_mail": {
942            "type": "dict",
943            "children": {
944                "log": {
945                    "type": "string",
946                    "options": [
947                        {
948                            "value": "enable",
949                            "revisions": {
950                                "v6.0.11": True,
951                                "v6.0.0": True,
952                                "v6.0.5": True
953                            }
954                        },
955                        {
956                            "value": "disable",
957                            "revisions": {
958                                "v6.0.11": True,
959                                "v6.0.0": True,
960                                "v6.0.5": True
961                            }
962                        }
963                    ],
964                    "revisions": {
965                        "v6.0.11": True,
966                        "v6.0.0": True,
967                        "v6.0.5": True
968                    }
969                }
970            },
971            "revisions": {
972                "v6.0.11": True,
973                "v6.0.0": True,
974                "v6.0.5": True
975            }
976        },
977        "msn_hotmail": {
978            "type": "dict",
979            "children": {
980                "log": {
981                    "type": "string",
982                    "options": [
983                        {
984                            "value": "enable",
985                            "revisions": {
986                                "v6.0.11": True,
987                                "v6.0.0": True,
988                                "v6.0.5": True
989                            }
990                        },
991                        {
992                            "value": "disable",
993                            "revisions": {
994                                "v6.0.11": True,
995                                "v6.0.0": True,
996                                "v6.0.5": True
997                            }
998                        }
999                    ],
1000                    "revisions": {
1001                        "v6.0.11": True,
1002                        "v6.0.0": True,
1003                        "v6.0.5": True
1004                    }
1005                }
1006            },
1007            "revisions": {
1008                "v6.0.11": True,
1009                "v6.0.0": True,
1010                "v6.0.5": True
1011            }
1012        },
1013        "flow_based": {
1014            "type": "string",
1015            "options": [
1016                {
1017                    "value": "enable",
1018                    "revisions": {
1019                        "v6.0.11": True,
1020                        "v6.0.0": True,
1021                        "v6.0.5": True
1022                    }
1023                },
1024                {
1025                    "value": "disable",
1026                    "revisions": {
1027                        "v6.0.11": True,
1028                        "v6.0.0": True,
1029                        "v6.0.5": True
1030                    }
1031                }
1032            ],
1033            "revisions": {
1034                "v6.0.11": True,
1035                "v6.0.0": True,
1036                "v6.0.5": True
1037            }
1038        },
1039        "pop3": {
1040            "type": "dict",
1041            "children": {
1042                "action": {
1043                    "type": "string",
1044                    "options": [
1045                        {
1046                            "value": "pass",
1047                            "revisions": {
1048                                "v6.0.11": True,
1049                                "v6.0.0": True,
1050                                "v6.0.5": True
1051                            }
1052                        },
1053                        {
1054                            "value": "tag",
1055                            "revisions": {
1056                                "v6.0.11": True,
1057                                "v6.0.0": True,
1058                                "v6.0.5": True
1059                            }
1060                        }
1061                    ],
1062                    "revisions": {
1063                        "v6.0.11": True,
1064                        "v6.0.0": True,
1065                        "v6.0.5": True
1066                    }
1067                },
1068                "tag_msg": {
1069                    "type": "string",
1070                    "revisions": {
1071                        "v6.0.11": True,
1072                        "v6.0.0": True,
1073                        "v6.0.5": True
1074                    }
1075                },
1076                "log": {
1077                    "type": "string",
1078                    "options": [
1079                        {
1080                            "value": "enable",
1081                            "revisions": {
1082                                "v6.0.11": True,
1083                                "v6.0.0": True,
1084                                "v6.0.5": True
1085                            }
1086                        },
1087                        {
1088                            "value": "disable",
1089                            "revisions": {
1090                                "v6.0.11": True,
1091                                "v6.0.0": True,
1092                                "v6.0.5": True
1093                            }
1094                        }
1095                    ],
1096                    "revisions": {
1097                        "v6.0.11": True,
1098                        "v6.0.0": True,
1099                        "v6.0.5": True
1100                    }
1101                },
1102                "tag_type": {
1103                    "type": "list",
1104                    "options": [
1105                        {
1106                            "value": "subject",
1107                            "revisions": {
1108                                "v6.0.11": True,
1109                                "v6.0.0": True,
1110                                "v6.0.5": True
1111                            }
1112                        },
1113                        {
1114                            "value": "header",
1115                            "revisions": {
1116                                "v6.0.11": True,
1117                                "v6.0.0": True,
1118                                "v6.0.5": True
1119                            }
1120                        },
1121                        {
1122                            "value": "spaminfo",
1123                            "revisions": {
1124                                "v6.0.11": True,
1125                                "v6.0.0": True,
1126                                "v6.0.5": True
1127                            }
1128                        }
1129                    ],
1130                    "revisions": {
1131                        "v6.0.11": True,
1132                        "v6.0.0": True,
1133                        "v6.0.5": True
1134                    }
1135                }
1136            },
1137            "revisions": {
1138                "v6.0.11": True,
1139                "v6.0.0": True,
1140                "v6.0.5": True
1141            }
1142        },
1143        "external": {
1144            "type": "string",
1145            "options": [
1146                {
1147                    "value": "enable",
1148                    "revisions": {
1149                        "v6.0.11": True,
1150                        "v6.0.0": True,
1151                        "v6.0.5": True
1152                    }
1153                },
1154                {
1155                    "value": "disable",
1156                    "revisions": {
1157                        "v6.0.11": True,
1158                        "v6.0.0": True,
1159                        "v6.0.5": True
1160                    }
1161                }
1162            ],
1163            "revisions": {
1164                "v6.0.11": True,
1165                "v6.0.0": True,
1166                "v6.0.5": True
1167            }
1168        },
1169        "imap": {
1170            "type": "dict",
1171            "children": {
1172                "action": {
1173                    "type": "string",
1174                    "options": [
1175                        {
1176                            "value": "pass",
1177                            "revisions": {
1178                                "v6.0.11": True,
1179                                "v6.0.0": True,
1180                                "v6.0.5": True
1181                            }
1182                        },
1183                        {
1184                            "value": "tag",
1185                            "revisions": {
1186                                "v6.0.11": True,
1187                                "v6.0.0": True,
1188                                "v6.0.5": True
1189                            }
1190                        }
1191                    ],
1192                    "revisions": {
1193                        "v6.0.11": True,
1194                        "v6.0.0": True,
1195                        "v6.0.5": True
1196                    }
1197                },
1198                "tag_msg": {
1199                    "type": "string",
1200                    "revisions": {
1201                        "v6.0.11": True,
1202                        "v6.0.0": True,
1203                        "v6.0.5": True
1204                    }
1205                },
1206                "log": {
1207                    "type": "string",
1208                    "options": [
1209                        {
1210                            "value": "enable",
1211                            "revisions": {
1212                                "v6.0.11": True,
1213                                "v6.0.0": True,
1214                                "v6.0.5": True
1215                            }
1216                        },
1217                        {
1218                            "value": "disable",
1219                            "revisions": {
1220                                "v6.0.11": True,
1221                                "v6.0.0": True,
1222                                "v6.0.5": True
1223                            }
1224                        }
1225                    ],
1226                    "revisions": {
1227                        "v6.0.11": True,
1228                        "v6.0.0": True,
1229                        "v6.0.5": True
1230                    }
1231                },
1232                "tag_type": {
1233                    "type": "list",
1234                    "options": [
1235                        {
1236                            "value": "subject",
1237                            "revisions": {
1238                                "v6.0.11": True,
1239                                "v6.0.0": True,
1240                                "v6.0.5": True
1241                            }
1242                        },
1243                        {
1244                            "value": "header",
1245                            "revisions": {
1246                                "v6.0.11": True,
1247                                "v6.0.0": True,
1248                                "v6.0.5": True
1249                            }
1250                        },
1251                        {
1252                            "value": "spaminfo",
1253                            "revisions": {
1254                                "v6.0.11": True,
1255                                "v6.0.0": True,
1256                                "v6.0.5": True
1257                            }
1258                        }
1259                    ],
1260                    "revisions": {
1261                        "v6.0.11": True,
1262                        "v6.0.0": True,
1263                        "v6.0.5": True
1264                    }
1265                }
1266            },
1267            "revisions": {
1268                "v6.0.11": True,
1269                "v6.0.0": True,
1270                "v6.0.5": True
1271            }
1272        },
1273        "spam_log": {
1274            "type": "string",
1275            "options": [
1276                {
1277                    "value": "disable",
1278                    "revisions": {
1279                        "v6.0.11": True,
1280                        "v6.0.0": True,
1281                        "v6.0.5": True
1282                    }
1283                },
1284                {
1285                    "value": "enable",
1286                    "revisions": {
1287                        "v6.0.11": True,
1288                        "v6.0.0": True,
1289                        "v6.0.5": True
1290                    }
1291                }
1292            ],
1293            "revisions": {
1294                "v6.0.11": True,
1295                "v6.0.0": True,
1296                "v6.0.5": True
1297            }
1298        },
1299        "name": {
1300            "type": "string",
1301            "revisions": {
1302                "v6.0.11": True,
1303                "v6.0.0": True,
1304                "v6.0.5": True
1305            }
1306        },
1307        "spam_filtering": {
1308            "type": "string",
1309            "options": [
1310                {
1311                    "value": "enable",
1312                    "revisions": {
1313                        "v6.0.11": True,
1314                        "v6.0.0": True,
1315                        "v6.0.5": True
1316                    }
1317                },
1318                {
1319                    "value": "disable",
1320                    "revisions": {
1321                        "v6.0.11": True,
1322                        "v6.0.0": True,
1323                        "v6.0.5": True
1324                    }
1325                }
1326            ],
1327            "revisions": {
1328                "v6.0.11": True,
1329                "v6.0.0": True,
1330                "v6.0.5": True
1331            }
1332        },
1333        "options": {
1334            "type": "list",
1335            "options": [
1336                {
1337                    "value": "bannedword",
1338                    "revisions": {
1339                        "v6.0.11": True,
1340                        "v6.0.0": True,
1341                        "v6.0.5": True
1342                    }
1343                },
1344                {
1345                    "value": "spambwl",
1346                    "revisions": {
1347                        "v6.0.11": True,
1348                        "v6.0.0": True,
1349                        "v6.0.5": True
1350                    }
1351                },
1352                {
1353                    "value": "spamfsip",
1354                    "revisions": {
1355                        "v6.0.11": True,
1356                        "v6.0.0": True,
1357                        "v6.0.5": True
1358                    }
1359                },
1360                {
1361                    "value": "spamfssubmit",
1362                    "revisions": {
1363                        "v6.0.11": True,
1364                        "v6.0.0": True,
1365                        "v6.0.5": True
1366                    }
1367                },
1368                {
1369                    "value": "spamfschksum",
1370                    "revisions": {
1371                        "v6.0.11": True,
1372                        "v6.0.0": True,
1373                        "v6.0.5": True
1374                    }
1375                },
1376                {
1377                    "value": "spamfsurl",
1378                    "revisions": {
1379                        "v6.0.11": True,
1380                        "v6.0.0": True,
1381                        "v6.0.5": True
1382                    }
1383                },
1384                {
1385                    "value": "spamhelodns",
1386                    "revisions": {
1387                        "v6.0.11": True,
1388                        "v6.0.0": True,
1389                        "v6.0.5": True
1390                    }
1391                },
1392                {
1393                    "value": "spamraddrdns",
1394                    "revisions": {
1395                        "v6.0.11": True,
1396                        "v6.0.0": True,
1397                        "v6.0.5": True
1398                    }
1399                },
1400                {
1401                    "value": "spamrbl",
1402                    "revisions": {
1403                        "v6.0.11": True,
1404                        "v6.0.0": True,
1405                        "v6.0.5": True
1406                    }
1407                },
1408                {
1409                    "value": "spamhdrcheck",
1410                    "revisions": {
1411                        "v6.0.11": True,
1412                        "v6.0.0": True,
1413                        "v6.0.5": True
1414                    }
1415                },
1416                {
1417                    "value": "spamfsphish",
1418                    "revisions": {
1419                        "v6.0.11": True,
1420                        "v6.0.0": True,
1421                        "v6.0.5": True
1422                    }
1423                }
1424            ],
1425            "revisions": {
1426                "v6.0.11": True,
1427                "v6.0.0": True,
1428                "v6.0.5": True
1429            }
1430        },
1431        "spam_bwl_table": {
1432            "type": "integer",
1433            "revisions": {
1434                "v6.0.11": True,
1435                "v6.0.0": True,
1436                "v6.0.5": True
1437            }
1438        }
1439    },
1440    "revisions": {
1441        "v6.0.11": True,
1442        "v6.0.0": True,
1443        "v6.0.5": True
1444    }
1445}
1446
1447
1448def main():
1449    module_spec = schema_to_module_spec(versioned_schema)
1450    mkeyname = 'name'
1451    fields = {
1452        "access_token": {"required": False, "type": "str", "no_log": True},
1453        "enable_log": {"required": False, "type": bool},
1454        "vdom": {"required": False, "type": "str", "default": "root"},
1455        "state": {"required": True, "type": "str",
1456                  "choices": ["present", "absent"]},
1457        "spamfilter_profile": {
1458            "required": False, "type": "dict", "default": None,
1459            "options": {
1460            }
1461        }
1462    }
1463    for attribute_name in module_spec['options']:
1464        fields["spamfilter_profile"]['options'][attribute_name] = module_spec['options'][attribute_name]
1465        if mkeyname and mkeyname == attribute_name:
1466            fields["spamfilter_profile"]['options'][attribute_name]['required'] = True
1467
1468    check_legacy_fortiosapi()
1469    module = AnsibleModule(argument_spec=fields,
1470                           supports_check_mode=True)
1471
1472    versions_check_result = None
1473    if module._socket_path:
1474        connection = Connection(module._socket_path)
1475        if 'access_token' in module.params:
1476            connection.set_option('access_token', module.params['access_token'])
1477
1478        if 'enable_log' in module.params:
1479            connection.set_option('enable_log', module.params['enable_log'])
1480        else:
1481            connection.set_option('enable_log', False)
1482        fos = FortiOSHandler(connection, module, mkeyname)
1483        versions_check_result = check_schema_versioning(fos, versioned_schema, "spamfilter_profile")
1484
1485        is_error, has_changed, result = fortios_spamfilter(module.params, fos, module.check_mode)
1486
1487    else:
1488        module.fail_json(**FAIL_SOCKET_MSG)
1489
1490    if versions_check_result and versions_check_result['matched'] is False:
1491        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")
1492
1493    if not is_error:
1494        if versions_check_result and versions_check_result['matched'] is False:
1495            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
1496        else:
1497            module.exit_json(changed=has_changed, meta=result)
1498    else:
1499        if versions_check_result and versions_check_result['matched'] is False:
1500            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
1501        else:
1502            module.fail_json(msg="Error in repo", meta=result)
1503
1504
1505if __name__ == '__main__':
1506    main()
1507