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_spamfilter_profile 27short_description: Configure AntiSpam profiles 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 spamfilter feature and profile 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 spamfilter_profile: 76 description: 77 - Configure AntiSpam profiles. 78 default: null 79 type: dict 80 suboptions: 81 comment: 82 description: 83 - Comment. 84 type: str 85 external: 86 description: 87 - Enable/disable external Email inspection. 88 type: str 89 choices: 90 - enable 91 - disable 92 flow_based: 93 description: 94 - Enable/disable flow-based spam filtering. 95 type: str 96 choices: 97 - enable 98 - disable 99 gmail: 100 description: 101 - Gmail. 102 type: dict 103 suboptions: 104 log: 105 description: 106 - Enable/disable logging. 107 type: str 108 choices: 109 - enable 110 - disable 111 imap: 112 description: 113 - IMAP. 114 type: dict 115 suboptions: 116 action: 117 description: 118 - Action for spam email. 119 type: str 120 choices: 121 - pass 122 - tag 123 log: 124 description: 125 - Enable/disable logging. 126 type: str 127 choices: 128 - enable 129 - disable 130 tag_msg: 131 description: 132 - Subject text or header added to spam email. 133 type: str 134 tag_type: 135 description: 136 - Tag subject or header for spam email. 137 type: list 138 choices: 139 - subject 140 - header 141 - spaminfo 142 mapi: 143 description: 144 - MAPI. 145 type: dict 146 suboptions: 147 action: 148 description: 149 - Action for spam email. 150 type: str 151 choices: 152 - pass 153 - discard 154 log: 155 description: 156 - Enable/disable logging. 157 type: str 158 choices: 159 - enable 160 - disable 161 msn_hotmail: 162 description: 163 - MSN Hotmail. 164 type: dict 165 suboptions: 166 log: 167 description: 168 - Enable/disable logging. 169 type: str 170 choices: 171 - enable 172 - disable 173 name: 174 description: 175 - Profile name. 176 required: true 177 type: str 178 options: 179 description: 180 - Options. 181 type: list 182 choices: 183 - bannedword 184 - spambwl 185 - spamfsip 186 - spamfssubmit 187 - spamfschksum 188 - spamfsurl 189 - spamhelodns 190 - spamraddrdns 191 - spamrbl 192 - spamhdrcheck 193 - spamfsphish 194 pop3: 195 description: 196 - POP3. 197 type: dict 198 suboptions: 199 action: 200 description: 201 - Action for spam email. 202 type: str 203 choices: 204 - pass 205 - tag 206 log: 207 description: 208 - Enable/disable logging. 209 type: str 210 choices: 211 - enable 212 - disable 213 tag_msg: 214 description: 215 - Subject text or header added to spam email. 216 type: str 217 tag_type: 218 description: 219 - Tag subject or header for spam email. 220 type: list 221 choices: 222 - subject 223 - header 224 - spaminfo 225 replacemsg_group: 226 description: 227 - Replacement message group. Source system.replacemsg-group.name. 228 type: str 229 smtp: 230 description: 231 - SMTP. 232 type: dict 233 suboptions: 234 action: 235 description: 236 - Action for spam email. 237 type: str 238 choices: 239 - pass 240 - tag 241 - discard 242 hdrip: 243 description: 244 - Enable/disable SMTP email header IP checks for spamfsip, spamrbl and spambwl filters. 245 type: str 246 choices: 247 - disable 248 - enable 249 local_override: 250 description: 251 - Enable/disable local filter to override SMTP remote check result. 252 type: str 253 choices: 254 - disable 255 - enable 256 log: 257 description: 258 - Enable/disable logging. 259 type: str 260 choices: 261 - enable 262 - disable 263 tag_msg: 264 description: 265 - Subject text or header added to spam email. 266 type: str 267 tag_type: 268 description: 269 - Tag subject or header for spam email. 270 type: list 271 choices: 272 - subject 273 - header 274 - spaminfo 275 spam_bwl_table: 276 description: 277 - Anti-spam black/white list table ID. Source spamfilter.bwl.id. 278 type: int 279 spam_bword_table: 280 description: 281 - Anti-spam banned word table ID. Source spamfilter.bword.id. 282 type: int 283 spam_bword_threshold: 284 description: 285 - Spam banned word threshold. 286 type: int 287 spam_filtering: 288 description: 289 - Enable/disable spam filtering. 290 type: str 291 choices: 292 - enable 293 - disable 294 spam_iptrust_table: 295 description: 296 - Anti-spam IP trust table ID. Source spamfilter.iptrust.id. 297 type: int 298 spam_log: 299 description: 300 - Enable/disable spam logging for email filtering. 301 type: str 302 choices: 303 - disable 304 - enable 305 spam_log_fortiguard_response: 306 description: 307 - Enable/disable logging FortiGuard spam response. 308 type: str 309 choices: 310 - disable 311 - enable 312 spam_mheader_table: 313 description: 314 - Anti-spam MIME header table ID. Source spamfilter.mheader.id. 315 type: int 316 spam_rbl_table: 317 description: 318 - Anti-spam DNSBL table ID. Source spamfilter.dnsbl.id. 319 type: int 320 yahoo_mail: 321 description: 322 - Yahoo! Mail. 323 type: dict 324 suboptions: 325 log: 326 description: 327 - Enable/disable logging. 328 type: str 329 choices: 330 - enable 331 - disable 332''' 333 334EXAMPLES = ''' 335- hosts: fortigates 336 collections: 337 - fortinet.fortios 338 connection: httpapi 339 vars: 340 vdom: "root" 341 ansible_httpapi_use_ssl: yes 342 ansible_httpapi_validate_certs: no 343 ansible_httpapi_port: 443 344 tasks: 345 - name: Configure AntiSpam profiles. 346 fortios_spamfilter_profile: 347 vdom: "{{ vdom }}" 348 state: "present" 349 access_token: "<your_own_value>" 350 spamfilter_profile: 351 comment: "Comment." 352 external: "enable" 353 flow_based: "enable" 354 gmail: 355 log: "enable" 356 imap: 357 action: "pass" 358 log: "enable" 359 tag_msg: "<your_own_value>" 360 tag_type: "subject" 361 mapi: 362 action: "pass" 363 log: "enable" 364 msn_hotmail: 365 log: "enable" 366 name: "default_name_18" 367 options: "bannedword" 368 pop3: 369 action: "pass" 370 log: "enable" 371 tag_msg: "<your_own_value>" 372 tag_type: "subject" 373 replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)" 374 smtp: 375 action: "pass" 376 hdrip: "disable" 377 local_override: "disable" 378 log: "enable" 379 tag_msg: "<your_own_value>" 380 tag_type: "subject" 381 spam_bwl_table: "33 (source spamfilter.bwl.id)" 382 spam_bword_table: "34 (source spamfilter.bword.id)" 383 spam_bword_threshold: "35" 384 spam_filtering: "enable" 385 spam_iptrust_table: "37 (source spamfilter.iptrust.id)" 386 spam_log: "disable" 387 spam_log_fortiguard_response: "disable" 388 spam_mheader_table: "40 (source spamfilter.mheader.id)" 389 spam_rbl_table: "41 (source spamfilter.dnsbl.id)" 390 yahoo_mail: 391 log: "enable" 392 393''' 394 395RETURN = ''' 396build: 397 description: Build number of the fortigate image 398 returned: always 399 type: str 400 sample: '1547' 401http_method: 402 description: Last method used to provision the content into FortiGate 403 returned: always 404 type: str 405 sample: 'PUT' 406http_status: 407 description: Last result given by FortiGate on last operation applied 408 returned: always 409 type: str 410 sample: "200" 411mkey: 412 description: Master key (id) used in the last call to FortiGate 413 returned: success 414 type: str 415 sample: "id" 416name: 417 description: Name of the table used to fulfill the request 418 returned: always 419 type: str 420 sample: "urlfilter" 421path: 422 description: Path of the table used to fulfill the request 423 returned: always 424 type: str 425 sample: "webfilter" 426revision: 427 description: Internal revision number 428 returned: always 429 type: str 430 sample: "17.0.2.10658" 431serial: 432 description: Serial number of the unit 433 returned: always 434 type: str 435 sample: "FGVMEVYYQT3AB5352" 436status: 437 description: Indication of the operation's result 438 returned: always 439 type: str 440 sample: "success" 441vdom: 442 description: Virtual domain used 443 returned: always 444 type: str 445 sample: "root" 446version: 447 description: Version of the FortiGate 448 returned: always 449 type: str 450 sample: "v5.6.3" 451 452''' 453from ansible.module_utils.basic import AnsibleModule 454from ansible.module_utils.connection import Connection 455from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler 456from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi 457from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec 458from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning 459from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG 460from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison 461from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize 462 463 464def filter_spamfilter_profile_data(json): 465 option_list = ['comment', 'external', 'flow_based', 466 'gmail', 'imap', 'mapi', 467 'msn_hotmail', 'name', 'options', 468 'pop3', 'replacemsg_group', 'smtp', 469 'spam_bwl_table', 'spam_bword_table', 'spam_bword_threshold', 470 'spam_filtering', 'spam_iptrust_table', 'spam_log', 471 'spam_log_fortiguard_response', 'spam_mheader_table', 'spam_rbl_table', 472 'yahoo_mail'] 473 dictionary = {} 474 475 for attribute in option_list: 476 if attribute in json and json[attribute] is not None: 477 dictionary[attribute] = json[attribute] 478 479 return dictionary 480 481 482def flatten_single_path(data, path, index): 483 if not data or index == len(path) or path[index] not in data or not data[path[index]]: 484 return 485 486 if index == len(path) - 1: 487 data[path[index]] = ' '.join(str(elem) for elem in data[path[index]]) 488 elif isinstance(data[path[index]], list): 489 for value in data[path[index]]: 490 flatten_single_path(value, path, index + 1) 491 else: 492 flatten_single_path(data[path[index]], path, index + 1) 493 494 495def flatten_multilists_attributes(data): 496 multilist_attrs = [[u'options'], [u'imap', u'tag_type'], [u'pop3', u'tag_type'], [u'smtp', u'tag_type']] 497 498 for attr in multilist_attrs: 499 flatten_single_path(data, attr, 0) 500 501 return data 502 503 504def underscore_to_hyphen(data): 505 if isinstance(data, list): 506 for i, elem in enumerate(data): 507 data[i] = underscore_to_hyphen(elem) 508 elif isinstance(data, dict): 509 new_data = {} 510 for k, v in data.items(): 511 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 512 data = new_data 513 514 return data 515 516 517def spamfilter_profile(data, fos, check_mode=False): 518 519 vdom = data['vdom'] 520 521 state = data['state'] 522 523 spamfilter_profile_data = data['spamfilter_profile'] 524 spamfilter_profile_data = flatten_multilists_attributes(spamfilter_profile_data) 525 filtered_data = underscore_to_hyphen(filter_spamfilter_profile_data(spamfilter_profile_data)) 526 527 # check_mode starts from here 528 if check_mode: 529 mkey = fos.get_mkey('system', 'interface', filtered_data, vdom=vdom) 530 current_data = fos.get('system', 'interface', vdom=vdom, mkey=mkey) 531 is_existed = current_data and current_data.get('http_status') == 200 \ 532 and isinstance(current_data.get('results'), list) \ 533 and len(current_data['results']) > 0 534 535 # 2. if it exists and the state is 'present' then compare current settings with desired 536 if state == 'present' or state is True: 537 if mkey is None: 538 return False, True, filtered_data 539 540 # if mkey exists then compare each other 541 # record exits and they're matched or not 542 if is_existed: 543 is_same = is_same_comparison( 544 serialize(current_data['results'][0]), serialize(filtered_data)) 545 return False, not is_same, filtered_data 546 547 # record does not exist 548 return False, True, filtered_data 549 550 if state == 'absent': 551 if mkey is None: 552 return False, False, filtered_data 553 554 if is_existed: 555 return False, True, filtered_data 556 return False, False, filtered_data 557 558 return True, False, {'reason: ': 'Must provide state parameter'} 559 560 if state == "present" or state is True: 561 return fos.set('spamfilter', 562 'profile', 563 data=filtered_data, 564 vdom=vdom) 565 566 elif state == "absent": 567 return fos.delete('spamfilter', 568 'profile', 569 mkey=filtered_data['name'], 570 vdom=vdom) 571 else: 572 fos._module.fail_json(msg='state must be present or absent!') 573 574 575def is_successful_status(status): 576 return status['status'] == "success" or \ 577 status['http_method'] == "DELETE" and status['http_status'] == 404 578 579 580def fortios_spamfilter(data, fos, check_mode): 581 582 if data['spamfilter_profile']: 583 resp = spamfilter_profile(data, fos, check_mode) 584 else: 585 fos._module.fail_json(msg='missing task body: %s' % ('spamfilter_profile')) 586 if check_mode: 587 return resp 588 return not is_successful_status(resp), \ 589 resp['status'] == "success" and \ 590 (resp['revision_changed'] if 'revision_changed' in resp else True), \ 591 resp 592 593 594versioned_schema = { 595 "type": "list", 596 "children": { 597 "comment": { 598 "type": "string", 599 "revisions": { 600 "v6.0.11": True, 601 "v6.0.0": True, 602 "v6.0.5": True 603 } 604 }, 605 "spam_bword_threshold": { 606 "type": "integer", 607 "revisions": { 608 "v6.0.11": True, 609 "v6.0.0": True, 610 "v6.0.5": True 611 } 612 }, 613 "spam_iptrust_table": { 614 "type": "integer", 615 "revisions": { 616 "v6.0.11": True, 617 "v6.0.0": True, 618 "v6.0.5": True 619 } 620 }, 621 "spam_log_fortiguard_response": { 622 "type": "string", 623 "options": [ 624 { 625 "value": "disable", 626 "revisions": { 627 "v6.0.11": True, 628 "v6.0.0": True, 629 "v6.0.5": True 630 } 631 }, 632 { 633 "value": "enable", 634 "revisions": { 635 "v6.0.11": True, 636 "v6.0.0": True, 637 "v6.0.5": True 638 } 639 } 640 ], 641 "revisions": { 642 "v6.0.11": True, 643 "v6.0.0": True, 644 "v6.0.5": True 645 } 646 }, 647 "smtp": { 648 "type": "dict", 649 "children": { 650 "local_override": { 651 "type": "string", 652 "options": [ 653 { 654 "value": "disable", 655 "revisions": { 656 "v6.0.11": True, 657 "v6.0.0": True, 658 "v6.0.5": True 659 } 660 }, 661 { 662 "value": "enable", 663 "revisions": { 664 "v6.0.11": True, 665 "v6.0.0": True, 666 "v6.0.5": True 667 } 668 } 669 ], 670 "revisions": { 671 "v6.0.11": True, 672 "v6.0.0": True, 673 "v6.0.5": True 674 } 675 }, 676 "hdrip": { 677 "type": "string", 678 "options": [ 679 { 680 "value": "disable", 681 "revisions": { 682 "v6.0.11": True, 683 "v6.0.0": True, 684 "v6.0.5": True 685 } 686 }, 687 { 688 "value": "enable", 689 "revisions": { 690 "v6.0.11": True, 691 "v6.0.0": True, 692 "v6.0.5": True 693 } 694 } 695 ], 696 "revisions": { 697 "v6.0.11": True, 698 "v6.0.0": True, 699 "v6.0.5": True 700 } 701 }, 702 "log": { 703 "type": "string", 704 "options": [ 705 { 706 "value": "enable", 707 "revisions": { 708 "v6.0.11": True, 709 "v6.0.0": True, 710 "v6.0.5": True 711 } 712 }, 713 { 714 "value": "disable", 715 "revisions": { 716 "v6.0.11": True, 717 "v6.0.0": True, 718 "v6.0.5": True 719 } 720 } 721 ], 722 "revisions": { 723 "v6.0.11": True, 724 "v6.0.0": True, 725 "v6.0.5": True 726 } 727 }, 728 "action": { 729 "type": "string", 730 "options": [ 731 { 732 "value": "pass", 733 "revisions": { 734 "v6.0.11": True, 735 "v6.0.0": True, 736 "v6.0.5": True 737 } 738 }, 739 { 740 "value": "tag", 741 "revisions": { 742 "v6.0.11": True, 743 "v6.0.0": True, 744 "v6.0.5": True 745 } 746 }, 747 { 748 "value": "discard", 749 "revisions": { 750 "v6.0.11": True, 751 "v6.0.0": True, 752 "v6.0.5": True 753 } 754 } 755 ], 756 "revisions": { 757 "v6.0.11": True, 758 "v6.0.0": True, 759 "v6.0.5": True 760 } 761 }, 762 "tag_msg": { 763 "type": "string", 764 "revisions": { 765 "v6.0.11": True, 766 "v6.0.0": True, 767 "v6.0.5": True 768 } 769 }, 770 "tag_type": { 771 "type": "list", 772 "options": [ 773 { 774 "value": "subject", 775 "revisions": { 776 "v6.0.11": True, 777 "v6.0.0": True, 778 "v6.0.5": True 779 } 780 }, 781 { 782 "value": "header", 783 "revisions": { 784 "v6.0.11": True, 785 "v6.0.0": True, 786 "v6.0.5": True 787 } 788 }, 789 { 790 "value": "spaminfo", 791 "revisions": { 792 "v6.0.11": True, 793 "v6.0.0": True, 794 "v6.0.5": True 795 } 796 } 797 ], 798 "revisions": { 799 "v6.0.11": True, 800 "v6.0.0": True, 801 "v6.0.5": True 802 } 803 } 804 }, 805 "revisions": { 806 "v6.0.11": True, 807 "v6.0.0": True, 808 "v6.0.5": True 809 } 810 }, 811 "replacemsg_group": { 812 "type": "string", 813 "revisions": { 814 "v6.0.11": True, 815 "v6.0.0": True, 816 "v6.0.5": True 817 } 818 }, 819 "gmail": { 820 "type": "dict", 821 "children": { 822 "log": { 823 "type": "string", 824 "options": [ 825 { 826 "value": "enable", 827 "revisions": { 828 "v6.0.11": True, 829 "v6.0.0": True, 830 "v6.0.5": True 831 } 832 }, 833 { 834 "value": "disable", 835 "revisions": { 836 "v6.0.11": True, 837 "v6.0.0": True, 838 "v6.0.5": True 839 } 840 } 841 ], 842 "revisions": { 843 "v6.0.11": True, 844 "v6.0.0": True, 845 "v6.0.5": True 846 } 847 } 848 }, 849 "revisions": { 850 "v6.0.11": True, 851 "v6.0.0": True, 852 "v6.0.5": True 853 } 854 }, 855 "spam_mheader_table": { 856 "type": "integer", 857 "revisions": { 858 "v6.0.11": True, 859 "v6.0.0": True, 860 "v6.0.5": True 861 } 862 }, 863 "spam_rbl_table": { 864 "type": "integer", 865 "revisions": { 866 "v6.0.11": True, 867 "v6.0.0": True, 868 "v6.0.5": True 869 } 870 }, 871 "mapi": { 872 "type": "dict", 873 "children": { 874 "action": { 875 "type": "string", 876 "options": [ 877 { 878 "value": "pass", 879 "revisions": { 880 "v6.0.11": True, 881 "v6.0.0": True, 882 "v6.0.5": True 883 } 884 }, 885 { 886 "value": "discard", 887 "revisions": { 888 "v6.0.11": True, 889 "v6.0.0": True, 890 "v6.0.5": True 891 } 892 } 893 ], 894 "revisions": { 895 "v6.0.11": True, 896 "v6.0.0": True, 897 "v6.0.5": True 898 } 899 }, 900 "log": { 901 "type": "string", 902 "options": [ 903 { 904 "value": "enable", 905 "revisions": { 906 "v6.0.11": True, 907 "v6.0.0": True, 908 "v6.0.5": True 909 } 910 }, 911 { 912 "value": "disable", 913 "revisions": { 914 "v6.0.11": True, 915 "v6.0.0": True, 916 "v6.0.5": True 917 } 918 } 919 ], 920 "revisions": { 921 "v6.0.11": True, 922 "v6.0.0": True, 923 "v6.0.5": True 924 } 925 } 926 }, 927 "revisions": { 928 "v6.0.11": True, 929 "v6.0.0": True, 930 "v6.0.5": True 931 } 932 }, 933 "spam_bword_table": { 934 "type": "integer", 935 "revisions": { 936 "v6.0.11": True, 937 "v6.0.0": True, 938 "v6.0.5": True 939 } 940 }, 941 "yahoo_mail": { 942 "type": "dict", 943 "children": { 944 "log": { 945 "type": "string", 946 "options": [ 947 { 948 "value": "enable", 949 "revisions": { 950 "v6.0.11": True, 951 "v6.0.0": True, 952 "v6.0.5": True 953 } 954 }, 955 { 956 "value": "disable", 957 "revisions": { 958 "v6.0.11": True, 959 "v6.0.0": True, 960 "v6.0.5": True 961 } 962 } 963 ], 964 "revisions": { 965 "v6.0.11": True, 966 "v6.0.0": True, 967 "v6.0.5": True 968 } 969 } 970 }, 971 "revisions": { 972 "v6.0.11": True, 973 "v6.0.0": True, 974 "v6.0.5": True 975 } 976 }, 977 "msn_hotmail": { 978 "type": "dict", 979 "children": { 980 "log": { 981 "type": "string", 982 "options": [ 983 { 984 "value": "enable", 985 "revisions": { 986 "v6.0.11": True, 987 "v6.0.0": True, 988 "v6.0.5": True 989 } 990 }, 991 { 992 "value": "disable", 993 "revisions": { 994 "v6.0.11": True, 995 "v6.0.0": True, 996 "v6.0.5": True 997 } 998 } 999 ], 1000 "revisions": { 1001 "v6.0.11": True, 1002 "v6.0.0": True, 1003 "v6.0.5": True 1004 } 1005 } 1006 }, 1007 "revisions": { 1008 "v6.0.11": True, 1009 "v6.0.0": True, 1010 "v6.0.5": True 1011 } 1012 }, 1013 "flow_based": { 1014 "type": "string", 1015 "options": [ 1016 { 1017 "value": "enable", 1018 "revisions": { 1019 "v6.0.11": True, 1020 "v6.0.0": True, 1021 "v6.0.5": True 1022 } 1023 }, 1024 { 1025 "value": "disable", 1026 "revisions": { 1027 "v6.0.11": True, 1028 "v6.0.0": True, 1029 "v6.0.5": True 1030 } 1031 } 1032 ], 1033 "revisions": { 1034 "v6.0.11": True, 1035 "v6.0.0": True, 1036 "v6.0.5": True 1037 } 1038 }, 1039 "pop3": { 1040 "type": "dict", 1041 "children": { 1042 "action": { 1043 "type": "string", 1044 "options": [ 1045 { 1046 "value": "pass", 1047 "revisions": { 1048 "v6.0.11": True, 1049 "v6.0.0": True, 1050 "v6.0.5": True 1051 } 1052 }, 1053 { 1054 "value": "tag", 1055 "revisions": { 1056 "v6.0.11": True, 1057 "v6.0.0": True, 1058 "v6.0.5": True 1059 } 1060 } 1061 ], 1062 "revisions": { 1063 "v6.0.11": True, 1064 "v6.0.0": True, 1065 "v6.0.5": True 1066 } 1067 }, 1068 "tag_msg": { 1069 "type": "string", 1070 "revisions": { 1071 "v6.0.11": True, 1072 "v6.0.0": True, 1073 "v6.0.5": True 1074 } 1075 }, 1076 "log": { 1077 "type": "string", 1078 "options": [ 1079 { 1080 "value": "enable", 1081 "revisions": { 1082 "v6.0.11": True, 1083 "v6.0.0": True, 1084 "v6.0.5": True 1085 } 1086 }, 1087 { 1088 "value": "disable", 1089 "revisions": { 1090 "v6.0.11": True, 1091 "v6.0.0": True, 1092 "v6.0.5": True 1093 } 1094 } 1095 ], 1096 "revisions": { 1097 "v6.0.11": True, 1098 "v6.0.0": True, 1099 "v6.0.5": True 1100 } 1101 }, 1102 "tag_type": { 1103 "type": "list", 1104 "options": [ 1105 { 1106 "value": "subject", 1107 "revisions": { 1108 "v6.0.11": True, 1109 "v6.0.0": True, 1110 "v6.0.5": True 1111 } 1112 }, 1113 { 1114 "value": "header", 1115 "revisions": { 1116 "v6.0.11": True, 1117 "v6.0.0": True, 1118 "v6.0.5": True 1119 } 1120 }, 1121 { 1122 "value": "spaminfo", 1123 "revisions": { 1124 "v6.0.11": True, 1125 "v6.0.0": True, 1126 "v6.0.5": True 1127 } 1128 } 1129 ], 1130 "revisions": { 1131 "v6.0.11": True, 1132 "v6.0.0": True, 1133 "v6.0.5": True 1134 } 1135 } 1136 }, 1137 "revisions": { 1138 "v6.0.11": True, 1139 "v6.0.0": True, 1140 "v6.0.5": True 1141 } 1142 }, 1143 "external": { 1144 "type": "string", 1145 "options": [ 1146 { 1147 "value": "enable", 1148 "revisions": { 1149 "v6.0.11": True, 1150 "v6.0.0": True, 1151 "v6.0.5": True 1152 } 1153 }, 1154 { 1155 "value": "disable", 1156 "revisions": { 1157 "v6.0.11": True, 1158 "v6.0.0": True, 1159 "v6.0.5": True 1160 } 1161 } 1162 ], 1163 "revisions": { 1164 "v6.0.11": True, 1165 "v6.0.0": True, 1166 "v6.0.5": True 1167 } 1168 }, 1169 "imap": { 1170 "type": "dict", 1171 "children": { 1172 "action": { 1173 "type": "string", 1174 "options": [ 1175 { 1176 "value": "pass", 1177 "revisions": { 1178 "v6.0.11": True, 1179 "v6.0.0": True, 1180 "v6.0.5": True 1181 } 1182 }, 1183 { 1184 "value": "tag", 1185 "revisions": { 1186 "v6.0.11": True, 1187 "v6.0.0": True, 1188 "v6.0.5": True 1189 } 1190 } 1191 ], 1192 "revisions": { 1193 "v6.0.11": True, 1194 "v6.0.0": True, 1195 "v6.0.5": True 1196 } 1197 }, 1198 "tag_msg": { 1199 "type": "string", 1200 "revisions": { 1201 "v6.0.11": True, 1202 "v6.0.0": True, 1203 "v6.0.5": True 1204 } 1205 }, 1206 "log": { 1207 "type": "string", 1208 "options": [ 1209 { 1210 "value": "enable", 1211 "revisions": { 1212 "v6.0.11": True, 1213 "v6.0.0": True, 1214 "v6.0.5": True 1215 } 1216 }, 1217 { 1218 "value": "disable", 1219 "revisions": { 1220 "v6.0.11": True, 1221 "v6.0.0": True, 1222 "v6.0.5": True 1223 } 1224 } 1225 ], 1226 "revisions": { 1227 "v6.0.11": True, 1228 "v6.0.0": True, 1229 "v6.0.5": True 1230 } 1231 }, 1232 "tag_type": { 1233 "type": "list", 1234 "options": [ 1235 { 1236 "value": "subject", 1237 "revisions": { 1238 "v6.0.11": True, 1239 "v6.0.0": True, 1240 "v6.0.5": True 1241 } 1242 }, 1243 { 1244 "value": "header", 1245 "revisions": { 1246 "v6.0.11": True, 1247 "v6.0.0": True, 1248 "v6.0.5": True 1249 } 1250 }, 1251 { 1252 "value": "spaminfo", 1253 "revisions": { 1254 "v6.0.11": True, 1255 "v6.0.0": True, 1256 "v6.0.5": True 1257 } 1258 } 1259 ], 1260 "revisions": { 1261 "v6.0.11": True, 1262 "v6.0.0": True, 1263 "v6.0.5": True 1264 } 1265 } 1266 }, 1267 "revisions": { 1268 "v6.0.11": True, 1269 "v6.0.0": True, 1270 "v6.0.5": True 1271 } 1272 }, 1273 "spam_log": { 1274 "type": "string", 1275 "options": [ 1276 { 1277 "value": "disable", 1278 "revisions": { 1279 "v6.0.11": True, 1280 "v6.0.0": True, 1281 "v6.0.5": True 1282 } 1283 }, 1284 { 1285 "value": "enable", 1286 "revisions": { 1287 "v6.0.11": True, 1288 "v6.0.0": True, 1289 "v6.0.5": True 1290 } 1291 } 1292 ], 1293 "revisions": { 1294 "v6.0.11": True, 1295 "v6.0.0": True, 1296 "v6.0.5": True 1297 } 1298 }, 1299 "name": { 1300 "type": "string", 1301 "revisions": { 1302 "v6.0.11": True, 1303 "v6.0.0": True, 1304 "v6.0.5": True 1305 } 1306 }, 1307 "spam_filtering": { 1308 "type": "string", 1309 "options": [ 1310 { 1311 "value": "enable", 1312 "revisions": { 1313 "v6.0.11": True, 1314 "v6.0.0": True, 1315 "v6.0.5": True 1316 } 1317 }, 1318 { 1319 "value": "disable", 1320 "revisions": { 1321 "v6.0.11": True, 1322 "v6.0.0": True, 1323 "v6.0.5": True 1324 } 1325 } 1326 ], 1327 "revisions": { 1328 "v6.0.11": True, 1329 "v6.0.0": True, 1330 "v6.0.5": True 1331 } 1332 }, 1333 "options": { 1334 "type": "list", 1335 "options": [ 1336 { 1337 "value": "bannedword", 1338 "revisions": { 1339 "v6.0.11": True, 1340 "v6.0.0": True, 1341 "v6.0.5": True 1342 } 1343 }, 1344 { 1345 "value": "spambwl", 1346 "revisions": { 1347 "v6.0.11": True, 1348 "v6.0.0": True, 1349 "v6.0.5": True 1350 } 1351 }, 1352 { 1353 "value": "spamfsip", 1354 "revisions": { 1355 "v6.0.11": True, 1356 "v6.0.0": True, 1357 "v6.0.5": True 1358 } 1359 }, 1360 { 1361 "value": "spamfssubmit", 1362 "revisions": { 1363 "v6.0.11": True, 1364 "v6.0.0": True, 1365 "v6.0.5": True 1366 } 1367 }, 1368 { 1369 "value": "spamfschksum", 1370 "revisions": { 1371 "v6.0.11": True, 1372 "v6.0.0": True, 1373 "v6.0.5": True 1374 } 1375 }, 1376 { 1377 "value": "spamfsurl", 1378 "revisions": { 1379 "v6.0.11": True, 1380 "v6.0.0": True, 1381 "v6.0.5": True 1382 } 1383 }, 1384 { 1385 "value": "spamhelodns", 1386 "revisions": { 1387 "v6.0.11": True, 1388 "v6.0.0": True, 1389 "v6.0.5": True 1390 } 1391 }, 1392 { 1393 "value": "spamraddrdns", 1394 "revisions": { 1395 "v6.0.11": True, 1396 "v6.0.0": True, 1397 "v6.0.5": True 1398 } 1399 }, 1400 { 1401 "value": "spamrbl", 1402 "revisions": { 1403 "v6.0.11": True, 1404 "v6.0.0": True, 1405 "v6.0.5": True 1406 } 1407 }, 1408 { 1409 "value": "spamhdrcheck", 1410 "revisions": { 1411 "v6.0.11": True, 1412 "v6.0.0": True, 1413 "v6.0.5": True 1414 } 1415 }, 1416 { 1417 "value": "spamfsphish", 1418 "revisions": { 1419 "v6.0.11": True, 1420 "v6.0.0": True, 1421 "v6.0.5": True 1422 } 1423 } 1424 ], 1425 "revisions": { 1426 "v6.0.11": True, 1427 "v6.0.0": True, 1428 "v6.0.5": True 1429 } 1430 }, 1431 "spam_bwl_table": { 1432 "type": "integer", 1433 "revisions": { 1434 "v6.0.11": True, 1435 "v6.0.0": True, 1436 "v6.0.5": True 1437 } 1438 } 1439 }, 1440 "revisions": { 1441 "v6.0.11": True, 1442 "v6.0.0": True, 1443 "v6.0.5": True 1444 } 1445} 1446 1447 1448def main(): 1449 module_spec = schema_to_module_spec(versioned_schema) 1450 mkeyname = 'name' 1451 fields = { 1452 "access_token": {"required": False, "type": "str", "no_log": True}, 1453 "enable_log": {"required": False, "type": bool}, 1454 "vdom": {"required": False, "type": "str", "default": "root"}, 1455 "state": {"required": True, "type": "str", 1456 "choices": ["present", "absent"]}, 1457 "spamfilter_profile": { 1458 "required": False, "type": "dict", "default": None, 1459 "options": { 1460 } 1461 } 1462 } 1463 for attribute_name in module_spec['options']: 1464 fields["spamfilter_profile"]['options'][attribute_name] = module_spec['options'][attribute_name] 1465 if mkeyname and mkeyname == attribute_name: 1466 fields["spamfilter_profile"]['options'][attribute_name]['required'] = True 1467 1468 check_legacy_fortiosapi() 1469 module = AnsibleModule(argument_spec=fields, 1470 supports_check_mode=True) 1471 1472 versions_check_result = None 1473 if module._socket_path: 1474 connection = Connection(module._socket_path) 1475 if 'access_token' in module.params: 1476 connection.set_option('access_token', module.params['access_token']) 1477 1478 if 'enable_log' in module.params: 1479 connection.set_option('enable_log', module.params['enable_log']) 1480 else: 1481 connection.set_option('enable_log', False) 1482 fos = FortiOSHandler(connection, module, mkeyname) 1483 versions_check_result = check_schema_versioning(fos, versioned_schema, "spamfilter_profile") 1484 1485 is_error, has_changed, result = fortios_spamfilter(module.params, fos, module.check_mode) 1486 1487 else: 1488 module.fail_json(**FAIL_SOCKET_MSG) 1489 1490 if versions_check_result and versions_check_result['matched'] is False: 1491 module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv") 1492 1493 if not is_error: 1494 if versions_check_result and versions_check_result['matched'] is False: 1495 module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result) 1496 else: 1497 module.exit_json(changed=has_changed, meta=result) 1498 else: 1499 if versions_check_result and versions_check_result['matched'] is False: 1500 module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result) 1501 else: 1502 module.fail_json(msg="Error in repo", meta=result) 1503 1504 1505if __name__ == '__main__': 1506 main() 1507