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