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_session_ttl
27short_description: Configure global session TTL timers for this FortiGate 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 session_ttl 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_session_ttl:
68        description:
69            - Configure global session TTL timers for this FortiGate.
70        default: null
71        type: dict
72        suboptions:
73            default:
74                description:
75                    - Default timeout.
76                type: str
77            port:
78                description:
79                    - Session TTL port.
80                type: list
81                suboptions:
82                    end_port:
83                        description:
84                            - End port number.
85                        type: int
86                    id:
87                        description:
88                            - Table entry ID.
89                        required: true
90                        type: int
91                    protocol:
92                        description:
93                            - Protocol (0 - 255).
94                        type: int
95                    start_port:
96                        description:
97                            - Start port number.
98                        type: int
99                    timeout:
100                        description:
101                            - Session timeout (TTL).
102                        type: str
103'''
104
105EXAMPLES = '''
106- hosts: fortigates
107  collections:
108    - fortinet.fortios
109  connection: httpapi
110  vars:
111   vdom: "root"
112   ansible_httpapi_use_ssl: yes
113   ansible_httpapi_validate_certs: no
114   ansible_httpapi_port: 443
115  tasks:
116  - name: Configure global session TTL timers for this FortiGate.
117    fortios_system_session_ttl:
118      vdom:  "{{ vdom }}"
119      system_session_ttl:
120        default: "<your_own_value>"
121        port:
122         -
123            end_port: "5"
124            id:  "6"
125            protocol: "7"
126            start_port: "8"
127            timeout: "<your_own_value>"
128
129'''
130
131RETURN = '''
132build:
133  description: Build number of the fortigate image
134  returned: always
135  type: str
136  sample: '1547'
137http_method:
138  description: Last method used to provision the content into FortiGate
139  returned: always
140  type: str
141  sample: 'PUT'
142http_status:
143  description: Last result given by FortiGate on last operation applied
144  returned: always
145  type: str
146  sample: "200"
147mkey:
148  description: Master key (id) used in the last call to FortiGate
149  returned: success
150  type: str
151  sample: "id"
152name:
153  description: Name of the table used to fulfill the request
154  returned: always
155  type: str
156  sample: "urlfilter"
157path:
158  description: Path of the table used to fulfill the request
159  returned: always
160  type: str
161  sample: "webfilter"
162revision:
163  description: Internal revision number
164  returned: always
165  type: str
166  sample: "17.0.2.10658"
167serial:
168  description: Serial number of the unit
169  returned: always
170  type: str
171  sample: "FGVMEVYYQT3AB5352"
172status:
173  description: Indication of the operation's result
174  returned: always
175  type: str
176  sample: "success"
177vdom:
178  description: Virtual domain used
179  returned: always
180  type: str
181  sample: "root"
182version:
183  description: Version of the FortiGate
184  returned: always
185  type: str
186  sample: "v5.6.3"
187
188'''
189from ansible.module_utils.basic import AnsibleModule
190from ansible.module_utils.connection import Connection
191from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
192from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
193from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
194from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
195from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
196from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
197from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize
198
199
200def filter_system_session_ttl_data(json):
201    option_list = ['default', 'port']
202    dictionary = {}
203
204    for attribute in option_list:
205        if attribute in json and json[attribute] is not None:
206            dictionary[attribute] = json[attribute]
207
208    return dictionary
209
210
211def underscore_to_hyphen(data):
212    if isinstance(data, list):
213        for i, elem in enumerate(data):
214            data[i] = underscore_to_hyphen(elem)
215    elif isinstance(data, dict):
216        new_data = {}
217        for k, v in data.items():
218            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
219        data = new_data
220
221    return data
222
223
224def system_session_ttl(data, fos):
225    vdom = data['vdom']
226    system_session_ttl_data = data['system_session_ttl']
227    filtered_data = underscore_to_hyphen(filter_system_session_ttl_data(system_session_ttl_data))
228
229    return fos.set('system',
230                   'session-ttl',
231                   data=filtered_data,
232                   vdom=vdom)
233
234
235def is_successful_status(status):
236    return status['status'] == "success" or \
237        status['http_method'] == "DELETE" and status['http_status'] == 404
238
239
240def fortios_system(data, fos):
241
242    if data['system_session_ttl']:
243        resp = system_session_ttl(data, fos)
244    else:
245        fos._module.fail_json(msg='missing task body: %s' % ('system_session_ttl'))
246
247    return not is_successful_status(resp), \
248        resp['status'] == "success" and \
249        (resp['revision_changed'] if 'revision_changed' in resp else True), \
250        resp
251
252
253versioned_schema = {
254    "type": "dict",
255    "children": {
256        "default": {
257            "type": "string",
258            "revisions": {
259                "v6.0.0": True,
260                "v7.0.0": True,
261                "v6.0.5": True,
262                "v6.4.4": True,
263                "v6.4.0": True,
264                "v6.4.1": True,
265                "v6.2.0": True,
266                "v6.2.3": True,
267                "v6.2.5": True,
268                "v6.2.7": True,
269                "v6.0.11": True
270            }
271        },
272        "port": {
273            "type": "list",
274            "children": {
275                "protocol": {
276                    "type": "integer",
277                    "revisions": {
278                        "v6.0.0": True,
279                        "v7.0.0": True,
280                        "v6.0.5": True,
281                        "v6.4.4": True,
282                        "v6.4.0": True,
283                        "v6.4.1": True,
284                        "v6.2.0": True,
285                        "v6.2.3": True,
286                        "v6.2.5": True,
287                        "v6.2.7": True,
288                        "v6.0.11": True
289                    }
290                },
291                "end_port": {
292                    "type": "integer",
293                    "revisions": {
294                        "v6.0.0": True,
295                        "v7.0.0": True,
296                        "v6.0.5": True,
297                        "v6.4.4": True,
298                        "v6.4.0": True,
299                        "v6.4.1": True,
300                        "v6.2.0": True,
301                        "v6.2.3": True,
302                        "v6.2.5": True,
303                        "v6.2.7": True,
304                        "v6.0.11": True
305                    }
306                },
307                "start_port": {
308                    "type": "integer",
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                "id": {
324                    "type": "integer",
325                    "revisions": {
326                        "v6.0.0": True,
327                        "v7.0.0": True,
328                        "v6.0.5": True,
329                        "v6.4.4": True,
330                        "v6.4.0": True,
331                        "v6.4.1": True,
332                        "v6.2.0": True,
333                        "v6.2.3": True,
334                        "v6.2.5": True,
335                        "v6.2.7": True,
336                        "v6.0.11": True
337                    }
338                },
339                "timeout": {
340                    "type": "string",
341                    "revisions": {
342                        "v6.0.0": True,
343                        "v7.0.0": True,
344                        "v6.0.5": True,
345                        "v6.4.4": True,
346                        "v6.4.0": True,
347                        "v6.4.1": True,
348                        "v6.2.0": True,
349                        "v6.2.3": True,
350                        "v6.2.5": True,
351                        "v6.2.7": True,
352                        "v6.0.11": True
353                    }
354                }
355            },
356            "revisions": {
357                "v6.0.0": True,
358                "v7.0.0": True,
359                "v6.0.5": True,
360                "v6.4.4": True,
361                "v6.4.0": True,
362                "v6.4.1": True,
363                "v6.2.0": True,
364                "v6.2.3": True,
365                "v6.2.5": True,
366                "v6.2.7": True,
367                "v6.0.11": True
368            }
369        }
370    },
371    "revisions": {
372        "v6.0.0": True,
373        "v7.0.0": True,
374        "v6.0.5": True,
375        "v6.4.4": True,
376        "v6.4.0": True,
377        "v6.4.1": True,
378        "v6.2.0": True,
379        "v6.2.3": True,
380        "v6.2.5": True,
381        "v6.2.7": True,
382        "v6.0.11": True
383    }
384}
385
386
387def main():
388    module_spec = schema_to_module_spec(versioned_schema)
389    mkeyname = None
390    fields = {
391        "access_token": {"required": False, "type": "str", "no_log": True},
392        "enable_log": {"required": False, "type": bool},
393        "vdom": {"required": False, "type": "str", "default": "root"},
394        "system_session_ttl": {
395            "required": False, "type": "dict", "default": None,
396            "options": {
397            }
398        }
399    }
400    for attribute_name in module_spec['options']:
401        fields["system_session_ttl"]['options'][attribute_name] = module_spec['options'][attribute_name]
402        if mkeyname and mkeyname == attribute_name:
403            fields["system_session_ttl"]['options'][attribute_name]['required'] = True
404
405    check_legacy_fortiosapi()
406    module = AnsibleModule(argument_spec=fields,
407                           supports_check_mode=False)
408
409    versions_check_result = None
410    if module._socket_path:
411        connection = Connection(module._socket_path)
412        if 'access_token' in module.params:
413            connection.set_option('access_token', module.params['access_token'])
414
415        if 'enable_log' in module.params:
416            connection.set_option('enable_log', module.params['enable_log'])
417        else:
418            connection.set_option('enable_log', False)
419        fos = FortiOSHandler(connection, module, mkeyname)
420        versions_check_result = check_schema_versioning(fos, versioned_schema, "system_session_ttl")
421
422        is_error, has_changed, result = fortios_system(module.params, fos)
423
424    else:
425        module.fail_json(**FAIL_SOCKET_MSG)
426
427    if versions_check_result and versions_check_result['matched'] is False:
428        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")
429
430    if not is_error:
431        if versions_check_result and versions_check_result['matched'] is False:
432            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
433        else:
434            module.exit_json(changed=has_changed, meta=result)
435    else:
436        if versions_check_result and versions_check_result['matched'] is False:
437            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
438        else:
439            module.fail_json(msg="Error in repo", meta=result)
440
441
442if __name__ == '__main__':
443    main()
444