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_vpn_ipsec_manualkey
27short_description: Configure IPsec manual keys 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 vpn_ipsec feature and manualkey 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    vpn_ipsec_manualkey:
76        description:
77            - Configure IPsec manual keys.
78        default: null
79        type: dict
80        suboptions:
81            authentication:
82                description:
83                    - Authentication algorithm. Must be the same for both ends of the tunnel.
84                type: str
85                choices:
86                    - null
87                    - md5
88                    - sha1
89                    - sha256
90                    - sha384
91                    - sha512
92            authkey:
93                description:
94                    - Hexadecimal authentication key in 16-digit (8-byte) segments separated by hyphens.
95                type: str
96            enckey:
97                description:
98                    - Hexadecimal encryption key in 16-digit (8-byte) segments separated by hyphens.
99                type: str
100            encryption:
101                description:
102                    - Encryption algorithm. Must be the same for both ends of the tunnel.
103                type: str
104                choices:
105                    - null
106                    - des
107                    - 3des
108                    - aes128
109                    - aes192
110                    - aes256
111                    - aria128
112                    - aria192
113                    - aria256
114                    - seed
115            interface:
116                description:
117                    - Name of the physical, aggregate, or VLAN interface. Source system.interface.name.
118                type: str
119            local_gw:
120                description:
121                    - Local gateway.
122                type: str
123            localspi:
124                description:
125                    - Local SPI, a hexadecimal 8-digit (4-byte) tag. Discerns between two traffic streams with different encryption rules.
126                type: str
127            name:
128                description:
129                    - IPsec tunnel name.
130                required: true
131                type: str
132            npu_offload:
133                description:
134                    - Enable/disable NPU offloading.
135                type: str
136                choices:
137                    - enable
138                    - disable
139            remote_gw:
140                description:
141                    - Peer gateway.
142                type: str
143            remotespi:
144                description:
145                    - Remote SPI, a hexadecimal 8-digit (4-byte) tag. Discerns between two traffic streams with different encryption rules.
146                type: str
147'''
148
149EXAMPLES = '''
150- hosts: fortigates
151  collections:
152    - fortinet.fortios
153  connection: httpapi
154  vars:
155   vdom: "root"
156   ansible_httpapi_use_ssl: yes
157   ansible_httpapi_validate_certs: no
158   ansible_httpapi_port: 443
159  tasks:
160  - name: Configure IPsec manual keys.
161    fortios_vpn_ipsec_manualkey:
162      vdom:  "{{ vdom }}"
163      state: "present"
164      access_token: "<your_own_value>"
165      vpn_ipsec_manualkey:
166        authentication: "null"
167        authkey: "<your_own_value>"
168        enckey: "<your_own_value>"
169        encryption: "null"
170        interface: "<your_own_value> (source system.interface.name)"
171        local_gw: "<your_own_value>"
172        localspi: "<your_own_value>"
173        name: "default_name_10"
174        npu_offload: "enable"
175        remote_gw: "<your_own_value>"
176        remotespi: "<your_own_value>"
177
178'''
179
180RETURN = '''
181build:
182  description: Build number of the fortigate image
183  returned: always
184  type: str
185  sample: '1547'
186http_method:
187  description: Last method used to provision the content into FortiGate
188  returned: always
189  type: str
190  sample: 'PUT'
191http_status:
192  description: Last result given by FortiGate on last operation applied
193  returned: always
194  type: str
195  sample: "200"
196mkey:
197  description: Master key (id) used in the last call to FortiGate
198  returned: success
199  type: str
200  sample: "id"
201name:
202  description: Name of the table used to fulfill the request
203  returned: always
204  type: str
205  sample: "urlfilter"
206path:
207  description: Path of the table used to fulfill the request
208  returned: always
209  type: str
210  sample: "webfilter"
211revision:
212  description: Internal revision number
213  returned: always
214  type: str
215  sample: "17.0.2.10658"
216serial:
217  description: Serial number of the unit
218  returned: always
219  type: str
220  sample: "FGVMEVYYQT3AB5352"
221status:
222  description: Indication of the operation's result
223  returned: always
224  type: str
225  sample: "success"
226vdom:
227  description: Virtual domain used
228  returned: always
229  type: str
230  sample: "root"
231version:
232  description: Version of the FortiGate
233  returned: always
234  type: str
235  sample: "v5.6.3"
236
237'''
238from ansible.module_utils.basic import AnsibleModule
239from ansible.module_utils.connection import Connection
240from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
241from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
242from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
243from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
244from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
245from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
246from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize
247
248
249def filter_vpn_ipsec_manualkey_data(json):
250    option_list = ['authentication', 'authkey', 'enckey',
251                   'encryption', 'interface', 'local_gw',
252                   'localspi', 'name', 'npu_offload',
253                   'remote_gw', 'remotespi']
254    dictionary = {}
255
256    for attribute in option_list:
257        if attribute in json and json[attribute] is not None:
258            dictionary[attribute] = json[attribute]
259
260    return dictionary
261
262
263def underscore_to_hyphen(data):
264    if isinstance(data, list):
265        for i, elem in enumerate(data):
266            data[i] = underscore_to_hyphen(elem)
267    elif isinstance(data, dict):
268        new_data = {}
269        for k, v in data.items():
270            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
271        data = new_data
272
273    return data
274
275
276def vpn_ipsec_manualkey(data, fos, check_mode=False):
277
278    vdom = data['vdom']
279
280    state = data['state']
281
282    vpn_ipsec_manualkey_data = data['vpn_ipsec_manualkey']
283    filtered_data = underscore_to_hyphen(filter_vpn_ipsec_manualkey_data(vpn_ipsec_manualkey_data))
284
285    # check_mode starts from here
286    if check_mode:
287        mkey = fos.get_mkey('system', 'interface', filtered_data, vdom=vdom)
288        current_data = fos.get('system', 'interface', vdom=vdom, mkey=mkey)
289        is_existed = current_data and current_data.get('http_status') == 200 \
290            and isinstance(current_data.get('results'), list) \
291            and len(current_data['results']) > 0
292
293        # 2. if it exists and the state is 'present' then compare current settings with desired
294        if state == 'present' or state is True:
295            if mkey is None:
296                return False, True, filtered_data
297
298            # if mkey exists then compare each other
299            # record exits and they're matched or not
300            if is_existed:
301                is_same = is_same_comparison(
302                    serialize(current_data['results'][0]), serialize(filtered_data))
303                return False, not is_same, filtered_data
304
305            # record does not exist
306            return False, True, filtered_data
307
308        if state == 'absent':
309            if mkey is None:
310                return False, False, filtered_data
311
312            if is_existed:
313                return False, True, filtered_data
314            return False, False, filtered_data
315
316        return True, False, {'reason: ': 'Must provide state parameter'}
317
318    if state == "present" or state is True:
319        return fos.set('vpn.ipsec',
320                       'manualkey',
321                       data=filtered_data,
322                       vdom=vdom)
323
324    elif state == "absent":
325        return fos.delete('vpn.ipsec',
326                          'manualkey',
327                          mkey=filtered_data['name'],
328                          vdom=vdom)
329    else:
330        fos._module.fail_json(msg='state must be present or absent!')
331
332
333def is_successful_status(status):
334    return status['status'] == "success" or \
335        status['http_method'] == "DELETE" and status['http_status'] == 404
336
337
338def fortios_vpn_ipsec(data, fos, check_mode):
339
340    if data['vpn_ipsec_manualkey']:
341        resp = vpn_ipsec_manualkey(data, fos, check_mode)
342    else:
343        fos._module.fail_json(msg='missing task body: %s' % ('vpn_ipsec_manualkey'))
344    if check_mode:
345        return resp
346    return not is_successful_status(resp), \
347        resp['status'] == "success" and \
348        (resp['revision_changed'] if 'revision_changed' in resp else True), \
349        resp
350
351
352versioned_schema = {
353    "type": "list",
354    "children": {
355        "name": {
356            "type": "string",
357            "revisions": {
358                "v6.0.0": True,
359                "v7.0.0": True,
360                "v6.0.5": True,
361                "v6.4.4": True,
362                "v6.4.0": True,
363                "v6.4.1": True,
364                "v6.2.0": True,
365                "v6.2.3": True,
366                "v6.2.5": True,
367                "v6.2.7": True,
368                "v6.0.11": True
369            }
370        },
371        "encryption": {
372            "type": "string",
373            "options": [
374                {
375                    "value": "null",
376                    "revisions": {
377                        "v6.0.0": True,
378                        "v7.0.0": True,
379                        "v6.0.5": True,
380                        "v6.4.4": True,
381                        "v6.4.0": True,
382                        "v6.4.1": True,
383                        "v6.2.0": True,
384                        "v6.2.3": True,
385                        "v6.2.5": True,
386                        "v6.2.7": True,
387                        "v6.0.11": True
388                    }
389                },
390                {
391                    "value": "des",
392                    "revisions": {
393                        "v6.0.0": True,
394                        "v7.0.0": True,
395                        "v6.0.5": True,
396                        "v6.4.4": True,
397                        "v6.4.0": True,
398                        "v6.4.1": True,
399                        "v6.2.0": True,
400                        "v6.2.3": True,
401                        "v6.2.5": True,
402                        "v6.2.7": True,
403                        "v6.0.11": True
404                    }
405                },
406                {
407                    "value": "3des",
408                    "revisions": {
409                        "v6.0.0": True,
410                        "v7.0.0": True,
411                        "v6.0.5": True,
412                        "v6.4.4": True,
413                        "v6.4.0": True,
414                        "v6.4.1": True,
415                        "v6.2.0": True,
416                        "v6.2.3": True,
417                        "v6.2.5": True,
418                        "v6.2.7": True,
419                        "v6.0.11": True
420                    }
421                },
422                {
423                    "value": "aes128",
424                    "revisions": {
425                        "v6.0.0": True,
426                        "v7.0.0": True,
427                        "v6.0.5": True,
428                        "v6.4.4": True,
429                        "v6.4.0": True,
430                        "v6.4.1": True,
431                        "v6.2.0": True,
432                        "v6.2.3": True,
433                        "v6.2.5": True,
434                        "v6.2.7": True,
435                        "v6.0.11": True
436                    }
437                },
438                {
439                    "value": "aes192",
440                    "revisions": {
441                        "v6.0.0": True,
442                        "v7.0.0": True,
443                        "v6.0.5": True,
444                        "v6.4.4": True,
445                        "v6.4.0": True,
446                        "v6.4.1": True,
447                        "v6.2.0": True,
448                        "v6.2.3": True,
449                        "v6.2.5": True,
450                        "v6.2.7": True,
451                        "v6.0.11": True
452                    }
453                },
454                {
455                    "value": "aes256",
456                    "revisions": {
457                        "v6.0.0": True,
458                        "v7.0.0": True,
459                        "v6.0.5": True,
460                        "v6.4.4": True,
461                        "v6.4.0": True,
462                        "v6.4.1": True,
463                        "v6.2.0": True,
464                        "v6.2.3": True,
465                        "v6.2.5": True,
466                        "v6.2.7": True,
467                        "v6.0.11": True
468                    }
469                },
470                {
471                    "value": "aria128",
472                    "revisions": {
473                        "v6.0.0": True,
474                        "v7.0.0": True,
475                        "v6.0.5": True,
476                        "v6.4.4": True,
477                        "v6.4.0": True,
478                        "v6.4.1": True,
479                        "v6.2.0": True,
480                        "v6.2.3": True,
481                        "v6.2.5": True,
482                        "v6.2.7": True,
483                        "v6.0.11": True
484                    }
485                },
486                {
487                    "value": "aria192",
488                    "revisions": {
489                        "v6.0.0": True,
490                        "v7.0.0": True,
491                        "v6.0.5": True,
492                        "v6.4.4": True,
493                        "v6.4.0": True,
494                        "v6.4.1": True,
495                        "v6.2.0": True,
496                        "v6.2.3": True,
497                        "v6.2.5": True,
498                        "v6.2.7": True,
499                        "v6.0.11": True
500                    }
501                },
502                {
503                    "value": "aria256",
504                    "revisions": {
505                        "v6.0.0": True,
506                        "v7.0.0": True,
507                        "v6.0.5": True,
508                        "v6.4.4": True,
509                        "v6.4.0": True,
510                        "v6.4.1": True,
511                        "v6.2.0": True,
512                        "v6.2.3": True,
513                        "v6.2.5": True,
514                        "v6.2.7": True,
515                        "v6.0.11": True
516                    }
517                },
518                {
519                    "value": "seed",
520                    "revisions": {
521                        "v6.0.0": True,
522                        "v7.0.0": True,
523                        "v6.0.5": True,
524                        "v6.4.4": True,
525                        "v6.4.0": True,
526                        "v6.4.1": True,
527                        "v6.2.0": True,
528                        "v6.2.3": True,
529                        "v6.2.5": True,
530                        "v6.2.7": True,
531                        "v6.0.11": True
532                    }
533                }
534            ],
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        "remotespi": {
550            "type": "string",
551            "revisions": {
552                "v6.0.0": True,
553                "v7.0.0": True,
554                "v6.0.5": True,
555                "v6.4.4": True,
556                "v6.4.0": True,
557                "v6.4.1": True,
558                "v6.2.0": True,
559                "v6.2.3": True,
560                "v6.2.5": True,
561                "v6.2.7": True,
562                "v6.0.11": True
563            }
564        },
565        "local_gw": {
566            "type": "string",
567            "revisions": {
568                "v6.0.0": True,
569                "v7.0.0": True,
570                "v6.0.5": True,
571                "v6.4.4": True,
572                "v6.4.0": True,
573                "v6.4.1": True,
574                "v6.2.0": True,
575                "v6.2.3": True,
576                "v6.2.5": True,
577                "v6.2.7": True,
578                "v6.0.11": True
579            }
580        },
581        "authkey": {
582            "type": "string",
583            "revisions": {
584                "v6.0.0": True,
585                "v7.0.0": True,
586                "v6.0.5": True,
587                "v6.4.4": True,
588                "v6.4.0": True,
589                "v6.4.1": True,
590                "v6.2.0": True,
591                "v6.2.3": True,
592                "v6.2.5": True,
593                "v6.2.7": True,
594                "v6.0.11": True
595            }
596        },
597        "authentication": {
598            "type": "string",
599            "options": [
600                {
601                    "value": "null",
602                    "revisions": {
603                        "v6.0.0": True,
604                        "v7.0.0": True,
605                        "v6.0.5": True,
606                        "v6.4.4": True,
607                        "v6.4.0": True,
608                        "v6.4.1": True,
609                        "v6.2.0": True,
610                        "v6.2.3": True,
611                        "v6.2.5": True,
612                        "v6.2.7": True,
613                        "v6.0.11": True
614                    }
615                },
616                {
617                    "value": "md5",
618                    "revisions": {
619                        "v6.0.0": True,
620                        "v7.0.0": True,
621                        "v6.0.5": True,
622                        "v6.4.4": True,
623                        "v6.4.0": True,
624                        "v6.4.1": True,
625                        "v6.2.0": True,
626                        "v6.2.3": True,
627                        "v6.2.5": True,
628                        "v6.2.7": True,
629                        "v6.0.11": True
630                    }
631                },
632                {
633                    "value": "sha1",
634                    "revisions": {
635                        "v6.0.0": True,
636                        "v7.0.0": True,
637                        "v6.0.5": True,
638                        "v6.4.4": True,
639                        "v6.4.0": True,
640                        "v6.4.1": True,
641                        "v6.2.0": True,
642                        "v6.2.3": True,
643                        "v6.2.5": True,
644                        "v6.2.7": True,
645                        "v6.0.11": True
646                    }
647                },
648                {
649                    "value": "sha256",
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                {
665                    "value": "sha384",
666                    "revisions": {
667                        "v6.0.0": True,
668                        "v7.0.0": True,
669                        "v6.0.5": True,
670                        "v6.4.4": True,
671                        "v6.4.0": True,
672                        "v6.4.1": True,
673                        "v6.2.0": True,
674                        "v6.2.3": True,
675                        "v6.2.5": True,
676                        "v6.2.7": True,
677                        "v6.0.11": True
678                    }
679                },
680                {
681                    "value": "sha512",
682                    "revisions": {
683                        "v6.0.0": True,
684                        "v7.0.0": True,
685                        "v6.0.5": True,
686                        "v6.4.4": True,
687                        "v6.4.0": True,
688                        "v6.4.1": True,
689                        "v6.2.0": True,
690                        "v6.2.3": True,
691                        "v6.2.5": True,
692                        "v6.2.7": True,
693                        "v6.0.11": True
694                    }
695                }
696            ],
697            "revisions": {
698                "v6.0.0": True,
699                "v7.0.0": True,
700                "v6.0.5": True,
701                "v6.4.4": True,
702                "v6.4.0": True,
703                "v6.4.1": True,
704                "v6.2.0": True,
705                "v6.2.3": True,
706                "v6.2.5": True,
707                "v6.2.7": True,
708                "v6.0.11": True
709            }
710        },
711        "enckey": {
712            "type": "string",
713            "revisions": {
714                "v6.0.0": True,
715                "v7.0.0": True,
716                "v6.0.5": True,
717                "v6.4.4": True,
718                "v6.4.0": True,
719                "v6.4.1": True,
720                "v6.2.0": True,
721                "v6.2.3": True,
722                "v6.2.5": True,
723                "v6.2.7": True,
724                "v6.0.11": True
725            }
726        },
727        "localspi": {
728            "type": "string",
729            "revisions": {
730                "v6.0.0": True,
731                "v7.0.0": True,
732                "v6.0.5": True,
733                "v6.4.4": True,
734                "v6.4.0": True,
735                "v6.4.1": True,
736                "v6.2.0": True,
737                "v6.2.3": True,
738                "v6.2.5": True,
739                "v6.2.7": True,
740                "v6.0.11": True
741            }
742        },
743        "interface": {
744            "type": "string",
745            "revisions": {
746                "v6.0.0": True,
747                "v7.0.0": True,
748                "v6.0.5": True,
749                "v6.4.4": True,
750                "v6.4.0": True,
751                "v6.4.1": True,
752                "v6.2.0": True,
753                "v6.2.3": True,
754                "v6.2.5": True,
755                "v6.2.7": True,
756                "v6.0.11": True
757            }
758        },
759        "remote_gw": {
760            "type": "string",
761            "revisions": {
762                "v6.0.0": True,
763                "v7.0.0": True,
764                "v6.0.5": True,
765                "v6.4.4": True,
766                "v6.4.0": True,
767                "v6.4.1": True,
768                "v6.2.0": True,
769                "v6.2.3": True,
770                "v6.2.5": True,
771                "v6.2.7": True,
772                "v6.0.11": True
773            }
774        },
775        "npu_offload": {
776            "type": "string",
777            "options": [
778                {
779                    "value": "enable",
780                    "revisions": {
781                        "v6.0.0": True,
782                        "v7.0.0": True,
783                        "v6.0.5": True,
784                        "v6.4.4": True,
785                        "v6.4.0": True,
786                        "v6.4.1": True,
787                        "v6.2.0": True,
788                        "v6.2.3": True,
789                        "v6.2.5": True,
790                        "v6.2.7": True,
791                        "v6.0.11": True
792                    }
793                },
794                {
795                    "value": "disable",
796                    "revisions": {
797                        "v6.0.0": True,
798                        "v7.0.0": True,
799                        "v6.0.5": True,
800                        "v6.4.4": True,
801                        "v6.4.0": True,
802                        "v6.4.1": True,
803                        "v6.2.0": True,
804                        "v6.2.3": True,
805                        "v6.2.5": True,
806                        "v6.2.7": True,
807                        "v6.0.11": True
808                    }
809                }
810            ],
811            "revisions": {
812                "v6.0.0": True,
813                "v7.0.0": False,
814                "v6.0.5": True,
815                "v6.4.4": True,
816                "v6.4.0": True,
817                "v6.4.1": True,
818                "v6.2.0": True,
819                "v6.2.3": True,
820                "v6.2.5": True,
821                "v6.2.7": True,
822                "v6.0.11": True
823            }
824        }
825    },
826    "revisions": {
827        "v6.0.0": True,
828        "v7.0.0": True,
829        "v6.0.5": True,
830        "v6.4.4": True,
831        "v6.4.0": True,
832        "v6.4.1": True,
833        "v6.2.0": True,
834        "v6.2.3": True,
835        "v6.2.5": True,
836        "v6.2.7": True,
837        "v6.0.11": True
838    }
839}
840
841
842def main():
843    module_spec = schema_to_module_spec(versioned_schema)
844    mkeyname = 'name'
845    fields = {
846        "access_token": {"required": False, "type": "str", "no_log": True},
847        "enable_log": {"required": False, "type": bool},
848        "vdom": {"required": False, "type": "str", "default": "root"},
849        "state": {"required": True, "type": "str",
850                  "choices": ["present", "absent"]},
851        "vpn_ipsec_manualkey": {
852            "required": False, "type": "dict", "default": None,
853            "options": {
854            }
855        }
856    }
857    for attribute_name in module_spec['options']:
858        fields["vpn_ipsec_manualkey"]['options'][attribute_name] = module_spec['options'][attribute_name]
859        if mkeyname and mkeyname == attribute_name:
860            fields["vpn_ipsec_manualkey"]['options'][attribute_name]['required'] = True
861
862    check_legacy_fortiosapi()
863    module = AnsibleModule(argument_spec=fields,
864                           supports_check_mode=True)
865
866    versions_check_result = None
867    if module._socket_path:
868        connection = Connection(module._socket_path)
869        if 'access_token' in module.params:
870            connection.set_option('access_token', module.params['access_token'])
871
872        if 'enable_log' in module.params:
873            connection.set_option('enable_log', module.params['enable_log'])
874        else:
875            connection.set_option('enable_log', False)
876        fos = FortiOSHandler(connection, module, mkeyname)
877        versions_check_result = check_schema_versioning(fos, versioned_schema, "vpn_ipsec_manualkey")
878
879        is_error, has_changed, result = fortios_vpn_ipsec(module.params, fos, module.check_mode)
880
881    else:
882        module.fail_json(**FAIL_SOCKET_MSG)
883
884    if versions_check_result and versions_check_result['matched'] is False:
885        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")
886
887    if not is_error:
888        if versions_check_result and versions_check_result['matched'] is False:
889            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
890        else:
891            module.exit_json(changed=has_changed, meta=result)
892    else:
893        if versions_check_result and versions_check_result['matched'] is False:
894            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
895        else:
896            module.fail_json(msg="Error in repo", meta=result)
897
898
899if __name__ == '__main__':
900    main()
901