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