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_router_setting
27short_description: Configure router settings in Fortinet's FortiOS and FortiGate.
28description:
29    - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
30      user to set and modify router feature and setting category.
31      Examples include all parameters and values need to be adjusted to datasources before usage.
32      Tested with FOS v6.0.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    router_setting:
68        description:
69            - Configure router settings.
70        default: null
71        type: dict
72        suboptions:
73            bgp_debug_flags:
74                description:
75                    - bgp_debug_flags
76                type: str
77            hostname:
78                description:
79                    - Hostname for this virtual domain router.
80                type: str
81            igmp_debug_flags:
82                description:
83                    - igmp_debug_flags
84                type: str
85            imi_debug_flags:
86                description:
87                    - imi_debug_flags
88                type: str
89            isis_debug_flags:
90                description:
91                    - isis_debug_flags
92                type: str
93            ospf6_debug_events_flags:
94                description:
95                    - ospf6_debug_events_flags
96                type: str
97            ospf6_debug_ifsm_flags:
98                description:
99                    - ospf6_debug_ifsm_flags
100                type: str
101            ospf6_debug_lsa_flags:
102                description:
103                    - ospf6_debug_lsa_flags
104                type: str
105            ospf6_debug_nfsm_flags:
106                description:
107                    - ospf6_debug_nfsm_flags
108                type: str
109            ospf6_debug_nsm_flags:
110                description:
111                    - ospf6_debug_nsm_flags
112                type: str
113            ospf6_debug_packet_flags:
114                description:
115                    - ospf6_debug_packet_flags
116                type: str
117            ospf6_debug_route_flags:
118                description:
119                    - ospf6_debug_route_flags
120                type: str
121            ospf_debug_events_flags:
122                description:
123                    - ospf_debug_events_flags
124                type: str
125            ospf_debug_ifsm_flags:
126                description:
127                    - ospf_debug_ifsm_flags
128                type: str
129            ospf_debug_lsa_flags:
130                description:
131                    - ospf_debug_lsa_flags
132                type: str
133            ospf_debug_nfsm_flags:
134                description:
135                    - ospf_debug_nfsm_flags
136                type: str
137            ospf_debug_nsm_flags:
138                description:
139                    - ospf_debug_nsm_flags
140                type: str
141            ospf_debug_packet_flags:
142                description:
143                    - ospf_debug_packet_flags
144                type: str
145            ospf_debug_route_flags:
146                description:
147                    - ospf_debug_route_flags
148                type: str
149            pimdm_debug_flags:
150                description:
151                    - pimdm_debug_flags
152                type: str
153            pimsm_debug_joinprune_flags:
154                description:
155                    - pimsm_debug_joinprune_flags
156                type: str
157            pimsm_debug_simple_flags:
158                description:
159                    - pimsm_debug_simple_flags
160                type: str
161            pimsm_debug_timer_flags:
162                description:
163                    - pimsm_debug_timer_flags
164                type: str
165            rip_debug_flags:
166                description:
167                    - rip_debug_flags
168                type: str
169            ripng_debug_flags:
170                description:
171                    - ripng_debug_flags
172                type: str
173            show_filter:
174                description:
175                    - Prefix-list as filter for showing routes. Source router.prefix-list.name.
176                type: str
177'''
178
179EXAMPLES = '''
180- hosts: fortigates
181  collections:
182    - fortinet.fortios
183  connection: httpapi
184  vars:
185   vdom: "root"
186   ansible_httpapi_use_ssl: yes
187   ansible_httpapi_validate_certs: no
188   ansible_httpapi_port: 443
189  tasks:
190  - name: Configure router settings.
191    fortios_router_setting:
192      vdom:  "{{ vdom }}"
193      router_setting:
194        bgp_debug_flags: "<your_own_value>"
195        hostname: "myhostname"
196        igmp_debug_flags: "<your_own_value>"
197        imi_debug_flags: "<your_own_value>"
198        isis_debug_flags: "<your_own_value>"
199        ospf6_debug_events_flags: "<your_own_value>"
200        ospf6_debug_ifsm_flags: "<your_own_value>"
201        ospf6_debug_lsa_flags: "<your_own_value>"
202        ospf6_debug_nfsm_flags: "<your_own_value>"
203        ospf6_debug_nsm_flags: "<your_own_value>"
204        ospf6_debug_packet_flags: "<your_own_value>"
205        ospf6_debug_route_flags: "<your_own_value>"
206        ospf_debug_events_flags: "<your_own_value>"
207        ospf_debug_ifsm_flags: "<your_own_value>"
208        ospf_debug_lsa_flags: "<your_own_value>"
209        ospf_debug_nfsm_flags: "<your_own_value>"
210        ospf_debug_nsm_flags: "<your_own_value>"
211        ospf_debug_packet_flags: "<your_own_value>"
212        ospf_debug_route_flags: "<your_own_value>"
213        pimdm_debug_flags: "<your_own_value>"
214        pimsm_debug_joinprune_flags: "<your_own_value>"
215        pimsm_debug_simple_flags: "<your_own_value>"
216        pimsm_debug_timer_flags: "<your_own_value>"
217        rip_debug_flags: "<your_own_value>"
218        ripng_debug_flags: "<your_own_value>"
219        show_filter: "<your_own_value> (source router.prefix-list.name)"
220
221'''
222
223RETURN = '''
224build:
225  description: Build number of the fortigate image
226  returned: always
227  type: str
228  sample: '1547'
229http_method:
230  description: Last method used to provision the content into FortiGate
231  returned: always
232  type: str
233  sample: 'PUT'
234http_status:
235  description: Last result given by FortiGate on last operation applied
236  returned: always
237  type: str
238  sample: "200"
239mkey:
240  description: Master key (id) used in the last call to FortiGate
241  returned: success
242  type: str
243  sample: "id"
244name:
245  description: Name of the table used to fulfill the request
246  returned: always
247  type: str
248  sample: "urlfilter"
249path:
250  description: Path of the table used to fulfill the request
251  returned: always
252  type: str
253  sample: "webfilter"
254revision:
255  description: Internal revision number
256  returned: always
257  type: str
258  sample: "17.0.2.10658"
259serial:
260  description: Serial number of the unit
261  returned: always
262  type: str
263  sample: "FGVMEVYYQT3AB5352"
264status:
265  description: Indication of the operation's result
266  returned: always
267  type: str
268  sample: "success"
269vdom:
270  description: Virtual domain used
271  returned: always
272  type: str
273  sample: "root"
274version:
275  description: Version of the FortiGate
276  returned: always
277  type: str
278  sample: "v5.6.3"
279
280'''
281from ansible.module_utils.basic import AnsibleModule
282from ansible.module_utils.connection import Connection
283from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
284from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
285from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
286from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
287from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
288from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
289from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize
290
291
292def filter_router_setting_data(json):
293    option_list = ['bgp_debug_flags', 'hostname', 'igmp_debug_flags',
294                   'imi_debug_flags', 'isis_debug_flags', 'ospf6_debug_events_flags',
295                   'ospf6_debug_ifsm_flags', 'ospf6_debug_lsa_flags', 'ospf6_debug_nfsm_flags',
296                   'ospf6_debug_nsm_flags', 'ospf6_debug_packet_flags', 'ospf6_debug_route_flags',
297                   'ospf_debug_events_flags', 'ospf_debug_ifsm_flags', 'ospf_debug_lsa_flags',
298                   'ospf_debug_nfsm_flags', 'ospf_debug_nsm_flags', 'ospf_debug_packet_flags',
299                   'ospf_debug_route_flags', 'pimdm_debug_flags', 'pimsm_debug_joinprune_flags',
300                   'pimsm_debug_simple_flags', 'pimsm_debug_timer_flags', 'rip_debug_flags',
301                   'ripng_debug_flags', 'show_filter']
302    dictionary = {}
303
304    for attribute in option_list:
305        if attribute in json and json[attribute] is not None:
306            dictionary[attribute] = json[attribute]
307
308    return dictionary
309
310
311def underscore_to_hyphen(data):
312    if isinstance(data, list):
313        for i, elem in enumerate(data):
314            data[i] = underscore_to_hyphen(elem)
315    elif isinstance(data, dict):
316        new_data = {}
317        for k, v in data.items():
318            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
319        data = new_data
320
321    return data
322
323
324def router_setting(data, fos):
325    vdom = data['vdom']
326    router_setting_data = data['router_setting']
327    filtered_data = underscore_to_hyphen(filter_router_setting_data(router_setting_data))
328
329    return fos.set('router',
330                   'setting',
331                   data=filtered_data,
332                   vdom=vdom)
333
334
335def is_successful_status(status):
336    return status['status'] == "success" or \
337        status['http_method'] == "DELETE" and status['http_status'] == 404
338
339
340def fortios_router(data, fos):
341
342    if data['router_setting']:
343        resp = router_setting(data, fos)
344    else:
345        fos._module.fail_json(msg='missing task body: %s' % ('router_setting'))
346
347    return not is_successful_status(resp), \
348        resp['status'] == "success" and \
349        (resp['revision_changed'] if 'revision_changed' in resp else True), \
350        resp
351
352
353versioned_schema = {
354    "type": "dict",
355    "children": {
356        "pimsm_debug_joinprune_flags": {
357            "type": "string",
358            "revisions": {
359                "v7.0.0": False,
360                "v6.4.4": False,
361                "v6.4.0": False,
362                "v6.4.1": False,
363                "v6.2.3": True,
364                "v6.2.5": False,
365                "v6.2.7": False
366            }
367        },
368        "igmp_debug_flags": {
369            "type": "string",
370            "revisions": {
371                "v7.0.0": False,
372                "v6.4.4": False,
373                "v6.4.0": False,
374                "v6.4.1": False,
375                "v6.2.3": True,
376                "v6.2.5": False,
377                "v6.2.7": False
378            }
379        },
380        "ospf_debug_nfsm_flags": {
381            "type": "string",
382            "revisions": {
383                "v7.0.0": False,
384                "v6.4.4": False,
385                "v6.4.0": False,
386                "v6.4.1": False,
387                "v6.2.3": True,
388                "v6.2.5": False,
389                "v6.2.7": False
390            }
391        },
392        "ospf_debug_packet_flags": {
393            "type": "string",
394            "revisions": {
395                "v7.0.0": False,
396                "v6.4.4": False,
397                "v6.4.0": False,
398                "v6.4.1": False,
399                "v6.2.3": True,
400                "v6.2.5": False,
401                "v6.2.7": False
402            }
403        },
404        "ospf6_debug_lsa_flags": {
405            "type": "string",
406            "revisions": {
407                "v7.0.0": False,
408                "v6.4.4": False,
409                "v6.4.0": False,
410                "v6.4.1": False,
411                "v6.2.3": True,
412                "v6.2.5": False,
413                "v6.2.7": False
414            }
415        },
416        "ospf_debug_nsm_flags": {
417            "type": "string",
418            "revisions": {
419                "v7.0.0": False,
420                "v6.4.4": False,
421                "v6.4.0": False,
422                "v6.4.1": False,
423                "v6.2.3": True,
424                "v6.2.5": False,
425                "v6.2.7": False
426            }
427        },
428        "ospf6_debug_nsm_flags": {
429            "type": "string",
430            "revisions": {
431                "v7.0.0": False,
432                "v6.4.4": False,
433                "v6.4.0": False,
434                "v6.4.1": False,
435                "v6.2.3": True,
436                "v6.2.5": False,
437                "v6.2.7": False
438            }
439        },
440        "ospf_debug_events_flags": {
441            "type": "string",
442            "revisions": {
443                "v7.0.0": False,
444                "v6.4.4": False,
445                "v6.4.0": False,
446                "v6.4.1": False,
447                "v6.2.3": True,
448                "v6.2.5": False,
449                "v6.2.7": False
450            }
451        },
452        "hostname": {
453            "type": "string",
454            "revisions": {
455                "v6.0.0": True,
456                "v7.0.0": True,
457                "v6.0.5": True,
458                "v6.4.4": True,
459                "v6.4.0": True,
460                "v6.4.1": True,
461                "v6.2.0": True,
462                "v6.2.3": True,
463                "v6.2.5": True,
464                "v6.2.7": True,
465                "v6.0.11": True
466            }
467        },
468        "bgp_debug_flags": {
469            "type": "string",
470            "revisions": {
471                "v7.0.0": False,
472                "v6.4.4": False,
473                "v6.4.0": False,
474                "v6.4.1": False,
475                "v6.2.3": True,
476                "v6.2.5": False,
477                "v6.2.7": False
478            }
479        },
480        "rip_debug_flags": {
481            "type": "string",
482            "revisions": {
483                "v7.0.0": False,
484                "v6.4.4": False,
485                "v6.4.0": False,
486                "v6.4.1": False,
487                "v6.2.3": True,
488                "v6.2.5": False,
489                "v6.2.7": False
490            }
491        },
492        "ospf_debug_ifsm_flags": {
493            "type": "string",
494            "revisions": {
495                "v7.0.0": False,
496                "v6.4.4": False,
497                "v6.4.0": False,
498                "v6.4.1": False,
499                "v6.2.3": True,
500                "v6.2.5": False,
501                "v6.2.7": False
502            }
503        },
504        "ospf_debug_route_flags": {
505            "type": "string",
506            "revisions": {
507                "v7.0.0": False,
508                "v6.4.4": False,
509                "v6.4.0": False,
510                "v6.4.1": False,
511                "v6.2.3": True,
512                "v6.2.5": False,
513                "v6.2.7": False
514            }
515        },
516        "ospf6_debug_route_flags": {
517            "type": "string",
518            "revisions": {
519                "v7.0.0": False,
520                "v6.4.4": False,
521                "v6.4.0": False,
522                "v6.4.1": False,
523                "v6.2.3": True,
524                "v6.2.5": False,
525                "v6.2.7": False
526            }
527        },
528        "ospf6_debug_nfsm_flags": {
529            "type": "string",
530            "revisions": {
531                "v7.0.0": False,
532                "v6.4.4": False,
533                "v6.4.0": False,
534                "v6.4.1": False,
535                "v6.2.3": True,
536                "v6.2.5": False,
537                "v6.2.7": False
538            }
539        },
540        "ospf_debug_lsa_flags": {
541            "type": "string",
542            "revisions": {
543                "v7.0.0": False,
544                "v6.4.4": False,
545                "v6.4.0": False,
546                "v6.4.1": False,
547                "v6.2.3": True,
548                "v6.2.5": False,
549                "v6.2.7": False
550            }
551        },
552        "pimsm_debug_simple_flags": {
553            "type": "string",
554            "revisions": {
555                "v7.0.0": False,
556                "v6.4.4": False,
557                "v6.4.0": False,
558                "v6.4.1": False,
559                "v6.2.3": True,
560                "v6.2.5": False,
561                "v6.2.7": False
562            }
563        },
564        "ripng_debug_flags": {
565            "type": "string",
566            "revisions": {
567                "v7.0.0": False,
568                "v6.4.4": False,
569                "v6.4.0": False,
570                "v6.4.1": False,
571                "v6.2.3": True,
572                "v6.2.5": False,
573                "v6.2.7": False
574            }
575        },
576        "pimsm_debug_timer_flags": {
577            "type": "string",
578            "revisions": {
579                "v7.0.0": False,
580                "v6.4.4": False,
581                "v6.4.0": False,
582                "v6.4.1": False,
583                "v6.2.3": True,
584                "v6.2.5": False,
585                "v6.2.7": False
586            }
587        },
588        "ospf6_debug_events_flags": {
589            "type": "string",
590            "revisions": {
591                "v7.0.0": False,
592                "v6.4.4": False,
593                "v6.4.0": False,
594                "v6.4.1": False,
595                "v6.2.3": True,
596                "v6.2.5": False,
597                "v6.2.7": False
598            }
599        },
600        "imi_debug_flags": {
601            "type": "string",
602            "revisions": {
603                "v7.0.0": False,
604                "v6.4.4": False,
605                "v6.4.0": False,
606                "v6.4.1": False,
607                "v6.2.3": True,
608                "v6.2.5": False,
609                "v6.2.7": False
610            }
611        },
612        "ospf6_debug_packet_flags": {
613            "type": "string",
614            "revisions": {
615                "v7.0.0": False,
616                "v6.4.4": False,
617                "v6.4.0": False,
618                "v6.4.1": False,
619                "v6.2.3": True,
620                "v6.2.5": False,
621                "v6.2.7": False
622            }
623        },
624        "isis_debug_flags": {
625            "type": "string",
626            "revisions": {
627                "v7.0.0": False,
628                "v6.4.4": False,
629                "v6.4.0": False,
630                "v6.4.1": False,
631                "v6.2.3": True,
632                "v6.2.5": False,
633                "v6.2.7": False
634            }
635        },
636        "show_filter": {
637            "type": "string",
638            "revisions": {
639                "v6.0.0": True,
640                "v7.0.0": True,
641                "v6.0.5": True,
642                "v6.4.4": True,
643                "v6.4.0": True,
644                "v6.4.1": True,
645                "v6.2.0": True,
646                "v6.2.3": True,
647                "v6.2.5": True,
648                "v6.2.7": True,
649                "v6.0.11": True
650            }
651        },
652        "pimdm_debug_flags": {
653            "type": "string",
654            "revisions": {
655                "v7.0.0": False,
656                "v6.4.4": False,
657                "v6.4.0": False,
658                "v6.4.1": False,
659                "v6.2.3": True,
660                "v6.2.5": False,
661                "v6.2.7": False
662            }
663        },
664        "ospf6_debug_ifsm_flags": {
665            "type": "string",
666            "revisions": {
667                "v7.0.0": False,
668                "v6.4.4": False,
669                "v6.4.0": False,
670                "v6.4.1": False,
671                "v6.2.3": True,
672                "v6.2.5": False,
673                "v6.2.7": False
674            }
675        }
676    },
677    "revisions": {
678        "v6.0.0": True,
679        "v7.0.0": True,
680        "v6.0.5": True,
681        "v6.4.4": True,
682        "v6.4.0": True,
683        "v6.4.1": True,
684        "v6.2.0": True,
685        "v6.2.3": True,
686        "v6.2.5": True,
687        "v6.2.7": True,
688        "v6.0.11": True
689    }
690}
691
692
693def main():
694    module_spec = schema_to_module_spec(versioned_schema)
695    mkeyname = None
696    fields = {
697        "access_token": {"required": False, "type": "str", "no_log": True},
698        "enable_log": {"required": False, "type": bool},
699        "vdom": {"required": False, "type": "str", "default": "root"},
700        "router_setting": {
701            "required": False, "type": "dict", "default": None,
702            "options": {
703            }
704        }
705    }
706    for attribute_name in module_spec['options']:
707        fields["router_setting"]['options'][attribute_name] = module_spec['options'][attribute_name]
708        if mkeyname and mkeyname == attribute_name:
709            fields["router_setting"]['options'][attribute_name]['required'] = True
710
711    check_legacy_fortiosapi()
712    module = AnsibleModule(argument_spec=fields,
713                           supports_check_mode=False)
714
715    versions_check_result = None
716    if module._socket_path:
717        connection = Connection(module._socket_path)
718        if 'access_token' in module.params:
719            connection.set_option('access_token', module.params['access_token'])
720
721        if 'enable_log' in module.params:
722            connection.set_option('enable_log', module.params['enable_log'])
723        else:
724            connection.set_option('enable_log', False)
725        fos = FortiOSHandler(connection, module, mkeyname)
726        versions_check_result = check_schema_versioning(fos, versioned_schema, "router_setting")
727
728        is_error, has_changed, result = fortios_router(module.params, fos)
729
730    else:
731        module.fail_json(**FAIL_SOCKET_MSG)
732
733    if versions_check_result and versions_check_result['matched'] is False:
734        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")
735
736    if not is_error:
737        if versions_check_result and versions_check_result['matched'] is False:
738            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
739        else:
740            module.exit_json(changed=has_changed, meta=result)
741    else:
742        if versions_check_result and versions_check_result['matched'] is False:
743            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
744        else:
745            module.fail_json(msg="Error in repo", meta=result)
746
747
748if __name__ == '__main__':
749    main()
750