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