From a171b80a0c6acc2212c131338a5e301606f45269 Mon Sep 17 00:00:00 2001 From: ftntcorecse <43451990+ftntcorecse@users.noreply.github.com> Date: Tue, 20 Nov 2018 22:15:00 -0700 Subject: [PATCH] FortiManager Web Filter Security Profile (#47150) * Initial Commit * Initial Commit * Initial Commit * Fixing syntax errors * After running sanity tests, fixed pylint and pep8 errors * After running sanity tests, fixed pylint and pep8 errors * Fixing more syntax issues * Fixing more syntax issues * Adding username to doc block * PR candidate * PR candidate * fixed pep8 and docs issues * fixed 2.6 function issues * fixed 2.6 function issues part duex * Initial commit for security profile group module * Adding better playbook example to module * Adding another commit to test shippable tests * Fixing shippable errors, pep8 in unit test file and doc block problem in main module * Fixing documentation module error * Fixing pep8 line too long in unit test * Fixing utility function with nested dictionaries * Fixing utility function with pep8 issue * Adding change to allow for multiple list of dictionaries to be submitted via a single playbook * Initial commit for FMG Security Profile Web Application Firewall * adding extra line at bottom for pep8 conditions * Adding descriptions to documentation * Fixing more pep8 issues * New commit for new PR * Removing todo in documentation * Changing module name in documentation to match actual module name * Fixing yaml syntax for long choices list * Fixing yaml syntax for long choices list * Initial commit for fmgr web filter security profile * Fixing pep8 syntax issues * Fixing documentation yaml syntax errors with choices on new lines * Fixing documentation yaml syntax errors, removing Todo comments * Fixing choices additional tab * Fixing choices on multiple lines * Fixing choices on multiple lines * Adding yaml block scalar for multiline choices * Changing YAML syntax for multiline to YAML sequence for choices * Fixing all sanity test errors * Fixing review changes * Adding @ in author names per @Gundalow's request per Ansible's guidelines --- .../network/fortimanager/fmgr_secprof_web.py | 1233 +++++++++++++++++ .../fixtures/test_fmgr_secprof_web.json | 214 +++ .../fortimanager/test_fmgr_secprof_web.py | 157 +++ 3 files changed, 1604 insertions(+) create mode 100644 lib/ansible/modules/network/fortimanager/fmgr_secprof_web.py create mode 100644 test/units/modules/network/fortimanager/fixtures/test_fmgr_secprof_web.json create mode 100644 test/units/modules/network/fortimanager/test_fmgr_secprof_web.py diff --git a/lib/ansible/modules/network/fortimanager/fmgr_secprof_web.py b/lib/ansible/modules/network/fortimanager/fmgr_secprof_web.py new file mode 100644 index 00000000000..1cb261ffec6 --- /dev/null +++ b/lib/ansible/modules/network/fortimanager/fmgr_secprof_web.py @@ -0,0 +1,1233 @@ +#!/usr/bin/python +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + +ANSIBLE_METADATA = {'status': ['preview'], + 'supported_by': 'community', + 'metadata_version': '1.1'} + +DOCUMENTATION = ''' +--- +module: fmgr_secprof_web +version_added: "2.8" +author: + - Luke Weighall (@lweighall) + - Andrew Welsh (@Ghilli3) + - Jim Huber (@p4r4n0y1ng) +short_description: Manage web filter security profiles in FortiManager +description: + - Manage web filter security profiles in FortiManager through playbooks using the FMG API + +options: + adom: + description: + - The ADOM the configuration should belong to. + required: false + default: root + + host: + description: + - The FortiManager's Address. + required: true + + username: + description: + - The username associated with the account. + required: true + + password: + description: + - The password associated with the username account. + required: true + + mode: + description: + - Sets one of three modes for managing the object. + - Allows use of soft-adds instead of overwriting existing values + choices: ['add', 'set', 'delete', 'update'] + required: false + default: add + + youtube_channel_status: + description: + - YouTube channel filter status. + - choice | disable | Disable YouTube channel filter. + - choice | blacklist | Block matches. + - choice | whitelist | Allow matches. + required: false + choices: ["disable", "blacklist", "whitelist"] + + wisp_servers: + description: + - WISP servers. + required: false + + wisp_algorithm: + description: + - WISP server selection algorithm. + - choice | auto-learning | Select the lightest loading healthy server. + - choice | primary-secondary | Select the first healthy server in order. + - choice | round-robin | Select the next healthy server. + required: false + choices: ["auto-learning", "primary-secondary", "round-robin"] + + wisp: + description: + - Enable/disable web proxy WISP. + - choice | disable | Disable web proxy WISP. + - choice | enable | Enable web proxy WISP. + required: false + choices: ["disable", "enable"] + + web_url_log: + description: + - Enable/disable logging URL filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_invalid_domain_log: + description: + - Enable/disable logging invalid domain names. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_ftgd_quota_usage: + description: + - Enable/disable logging daily quota usage. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_ftgd_err_log: + description: + - Enable/disable logging rating errors. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_vbs_log: + description: + - Enable/disable logging VBS scripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_unknown_log: + description: + - Enable/disable logging unknown scripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_referer_log: + description: + - Enable/disable logging referrers. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_jscript_log: + description: + - Enable/disable logging JScripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_js_log: + description: + - Enable/disable logging Java scripts. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_cookie_removal_log: + description: + - Enable/disable logging blocked cookies. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_cookie_log: + description: + - Enable/disable logging cookie filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_command_block_log: + description: + - Enable/disable logging blocked commands. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_applet_log: + description: + - Enable/disable logging Java applets. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_filter_activex_log: + description: + - Enable/disable logging ActiveX. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_extended_all_action_log: + description: + - Enable/disable extended any filter action logging for web filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_content_log: + description: + - Enable/disable logging logging blocked web content. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + replacemsg_group: + description: + - Replacement message group. + required: false + + post_action: + description: + - Action taken for HTTP POST traffic. + - choice | normal | Normal, POST requests are allowed. + - choice | block | POST requests are blocked. + required: false + choices: ["normal", "block"] + + ovrd_perm: + description: + - FLAG Based Options. Specify multiple in list form. + - flag | bannedword-override | Banned word override. + - flag | urlfilter-override | URL filter override. + - flag | fortiguard-wf-override | FortiGuard Web Filter override. + - flag | contenttype-check-override | Content-type header override. + required: false + choices: + - bannedword-override + - urlfilter-override + - fortiguard-wf-override + - contenttype-check-override + + options: + description: + - FLAG Based Options. Specify multiple in list form. + - flag | block-invalid-url | Block sessions contained an invalid domain name. + - flag | jscript | Javascript block. + - flag | js | JS block. + - flag | vbs | VB script block. + - flag | unknown | Unknown script block. + - flag | wf-referer | Referring block. + - flag | intrinsic | Intrinsic script block. + - flag | wf-cookie | Cookie block. + - flag | per-user-bwl | Per-user black/white list filter + - flag | activexfilter | ActiveX filter. + - flag | cookiefilter | Cookie filter. + - flag | javafilter | Java applet filter. + required: false + choices: + - block-invalid-url + - jscript + - js + - vbs + - unknown + - wf-referer + - intrinsic + - wf-cookie + - per-user-bwl + - activexfilter + - cookiefilter + - javafilter + + name: + description: + - Profile name. + required: false + + log_all_url: + description: + - Enable/disable logging all URLs visited. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + inspection_mode: + description: + - Web filtering inspection mode. + - choice | proxy | Proxy. + - choice | flow-based | Flow based. + required: false + choices: ["proxy", "flow-based"] + + https_replacemsg: + description: + - Enable replacement messages for HTTPS. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + extended_log: + description: + - Enable/disable extended logging for web filtering. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + comment: + description: + - Optional comments. + required: false + + ftgd_wf: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + ftgd_wf_exempt_quota: + description: + - Do not stop quota for these categories. + required: false + + ftgd_wf_max_quota_timeout: + description: + - Maximum FortiGuard quota used by single page view in seconds (excludes streams). + required: false + + ftgd_wf_options: + description: + - Options for FortiGuard Web Filter. + - FLAG Based Options. Specify multiple in list form. + - flag | error-allow | Allow web pages with a rating error to pass through. + - flag | rate-server-ip | Rate the server IP in addition to the domain name. + - flag | connect-request-bypass | Bypass connection which has CONNECT request. + - flag | ftgd-disable | Disable FortiGuard scanning. + required: false + choices: ["error-allow", "rate-server-ip", "connect-request-bypass", "ftgd-disable"] + + ftgd_wf_ovrd: + description: + - Allow web filter profile overrides. + required: false + + ftgd_wf_rate_crl_urls: + description: + - Enable/disable rating CRL by URL. + - choice | disable | Disable rating CRL by URL. + - choice | enable | Enable rating CRL by URL. + required: false + choices: ["disable", "enable"] + + ftgd_wf_rate_css_urls: + description: + - Enable/disable rating CSS by URL. + - choice | disable | Disable rating CSS by URL. + - choice | enable | Enable rating CSS by URL. + required: false + choices: ["disable", "enable"] + + ftgd_wf_rate_image_urls: + description: + - Enable/disable rating images by URL. + - choice | disable | Disable rating images by URL (blocked images are replaced with blanks). + - choice | enable | Enable rating images by URL (blocked images are replaced with blanks). + required: false + choices: ["disable", "enable"] + + ftgd_wf_rate_javascript_urls: + description: + - Enable/disable rating JavaScript by URL. + - choice | disable | Disable rating JavaScript by URL. + - choice | enable | Enable rating JavaScript by URL. + required: false + choices: ["disable", "enable"] + + ftgd_wf_filters_action: + description: + - Action to take for matches. + - choice | block | Block access. + - choice | monitor | Allow access while logging the action. + - choice | warning | Allow access after warning the user. + - choice | authenticate | Authenticate user before allowing access. + required: false + choices: ["block", "monitor", "warning", "authenticate"] + + ftgd_wf_filters_auth_usr_grp: + description: + - Groups with permission to authenticate. + required: false + + ftgd_wf_filters_category: + description: + - Categories and groups the filter examines. + required: false + + ftgd_wf_filters_log: + description: + - Enable/disable logging. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + ftgd_wf_filters_override_replacemsg: + description: + - Override replacement message. + required: false + + ftgd_wf_filters_warn_duration: + description: + - Duration of warnings. + required: false + + ftgd_wf_filters_warning_duration_type: + description: + - Re-display warning after closing browser or after a timeout. + - choice | session | After session ends. + - choice | timeout | After timeout occurs. + required: false + choices: ["session", "timeout"] + + ftgd_wf_filters_warning_prompt: + description: + - Warning prompts in each category or each domain. + - choice | per-domain | Per-domain warnings. + - choice | per-category | Per-category warnings. + required: false + choices: ["per-domain", "per-category"] + + ftgd_wf_quota_category: + description: + - FortiGuard categories to apply quota to (category action must be set to monitor). + required: false + + ftgd_wf_quota_duration: + description: + - Duration of quota. + required: false + + ftgd_wf_quota_override_replacemsg: + description: + - Override replacement message. + required: false + + ftgd_wf_quota_type: + description: + - Quota type. + - choice | time | Use a time-based quota. + - choice | traffic | Use a traffic-based quota. + required: false + choices: ["time", "traffic"] + + ftgd_wf_quota_unit: + description: + - Traffic quota unit of measurement. + - choice | B | Quota in bytes. + - choice | KB | Quota in kilobytes. + - choice | MB | Quota in megabytes. + - choice | GB | Quota in gigabytes. + required: false + choices: ["B", "KB", "MB", "GB"] + + ftgd_wf_quota_value: + description: + - Traffic quota value. + required: false + + override: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + override_ovrd_cookie: + description: + - Allow/deny browser-based (cookie) overrides. + - choice | deny | Deny browser-based (cookie) override. + - choice | allow | Allow browser-based (cookie) override. + required: false + choices: ["deny", "allow"] + + override_ovrd_dur: + description: + - Override duration. + required: false + + override_ovrd_dur_mode: + description: + - Override duration mode. + - choice | constant | Constant mode. + - choice | ask | Prompt for duration when initiating an override. + required: false + choices: ["constant", "ask"] + + override_ovrd_scope: + description: + - Override scope. + - choice | user | Override for the user. + - choice | user-group | Override for the user's group. + - choice | ip | Override for the initiating IP. + - choice | ask | Prompt for scope when initiating an override. + - choice | browser | Create browser-based (cookie) override. + required: false + choices: ["user", "user-group", "ip", "ask", "browser"] + + override_ovrd_user_group: + description: + - User groups with permission to use the override. + required: false + + override_profile: + description: + - Web filter profile with permission to create overrides. + required: false + + override_profile_attribute: + description: + - Profile attribute to retrieve from the RADIUS server. + - choice | User-Name | Use this attribute. + - choice | NAS-IP-Address | Use this attribute. + - choice | Framed-IP-Address | Use this attribute. + - choice | Framed-IP-Netmask | Use this attribute. + - choice | Filter-Id | Use this attribute. + - choice | Login-IP-Host | Use this attribute. + - choice | Reply-Message | Use this attribute. + - choice | Callback-Number | Use this attribute. + - choice | Callback-Id | Use this attribute. + - choice | Framed-Route | Use this attribute. + - choice | Framed-IPX-Network | Use this attribute. + - choice | Class | Use this attribute. + - choice | Called-Station-Id | Use this attribute. + - choice | Calling-Station-Id | Use this attribute. + - choice | NAS-Identifier | Use this attribute. + - choice | Proxy-State | Use this attribute. + - choice | Login-LAT-Service | Use this attribute. + - choice | Login-LAT-Node | Use this attribute. + - choice | Login-LAT-Group | Use this attribute. + - choice | Framed-AppleTalk-Zone | Use this attribute. + - choice | Acct-Session-Id | Use this attribute. + - choice | Acct-Multi-Session-Id | Use this attribute. + required: false + choices: + - User-Name + - NAS-IP-Address + - Framed-IP-Address + - Framed-IP-Netmask + - Filter-Id + - Login-IP-Host + - Reply-Message + - Callback-Number + - Callback-Id + - Framed-Route + - Framed-IPX-Network + - Class + - Called-Station-Id + - Calling-Station-Id + - NAS-Identifier + - Proxy-State + - Login-LAT-Service + - Login-LAT-Node + - Login-LAT-Group + - Framed-AppleTalk-Zone + - Acct-Session-Id + - Acct-Multi-Session-Id + + override_profile_type: + description: + - Override profile type. + - choice | list | Profile chosen from list. + - choice | radius | Profile determined by RADIUS server. + required: false + choices: ["list", "radius"] + + url_extraction: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + url_extraction_redirect_header: + description: + - HTTP header name to use for client redirect on blocked requests + required: false + + url_extraction_redirect_no_content: + description: + - Enable / Disable empty message-body entity in HTTP response + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + url_extraction_redirect_url: + description: + - HTTP header value to use for client redirect on blocked requests + required: false + + url_extraction_server_fqdn: + description: + - URL extraction server FQDN (fully qualified domain name) + required: false + + url_extraction_status: + description: + - Enable URL Extraction + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + web_blacklist: + description: + - Enable/disable automatic addition of URLs detected by FortiSandbox to blacklist. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_bword_table: + description: + - Banned word table ID. + required: false + + web_bword_threshold: + description: + - Banned word score threshold. + required: false + + web_content_header_list: + description: + - Content header list. + required: false + + web_keyword_match: + description: + - Search keywords to log when match is found. + required: false + + web_log_search: + description: + - Enable/disable logging all search phrases. + - choice | disable | Disable setting. + - choice | enable | Enable setting. + required: false + choices: ["disable", "enable"] + + web_safe_search: + description: + - Safe search type. + - FLAG Based Options. Specify multiple in list form. + - flag | url | Insert safe search string into URL. + - flag | header | Insert safe search header. + required: false + choices: ["url", "header"] + + web_urlfilter_table: + description: + - URL filter table ID. + required: false + + web_whitelist: + description: + - FortiGuard whitelist settings. + - FLAG Based Options. Specify multiple in list form. + - flag | exempt-av | Exempt antivirus. + - flag | exempt-webcontent | Exempt web content. + - flag | exempt-activex-java-cookie | Exempt ActiveX-JAVA-Cookie. + - flag | exempt-dlp | Exempt DLP. + - flag | exempt-rangeblock | Exempt RangeBlock. + - flag | extended-log-others | Support extended log. + required: false + choices: + - exempt-av + - exempt-webcontent + - exempt-activex-java-cookie + - exempt-dlp + - exempt-rangeblock + - extended-log-others + + web_youtube_restrict: + description: + - YouTube EDU filter level. + - choice | strict | Strict access for YouTube. + - choice | none | Full access for YouTube. + - choice | moderate | Moderate access for YouTube. + required: false + choices: ["strict", "none", "moderate"] + + youtube_channel_filter: + description: + - EXPERTS ONLY! KNOWLEDGE OF FMGR JSON API IS REQUIRED! + - List of multiple child objects to be added. Expects a list of dictionaries. + - Dictionaries must use FortiManager API parameters, not the ansible ones listed below. + - If submitted, all other prefixed sub-parameters ARE IGNORED. + - This object is MUTUALLY EXCLUSIVE with its options. + - We expect that you know what you are doing with these list parameters, and are leveraging the JSON API Guide. + - WHEN IN DOUBT, USE THE SUB OPTIONS BELOW INSTEAD TO CREATE OBJECTS WITH MULTIPLE TASKS + required: false + + youtube_channel_filter_channel_id: + description: + - YouTube channel ID to be filtered. + required: false + + youtube_channel_filter_comment: + description: + - Comment. + required: false + + +''' + +EXAMPLES = ''' + - name: DELETE Profile + fmgr_secprof_web: + host: "{{inventory_hostname}}" + username: "{{ username }}" + password: "{{ password }}" + name: "Ansible_Web_Filter_Profile" + mode: "delete" + + - name: CREATE Profile + fmgr_secprof_web: + host: "{{inventory_hostname}}" + username: "{{ username }}" + password: "{{ password }}" + name: "Ansible_Web_Filter_Profile" + comment: "Created by Ansible Module TEST" + mode: "set" + extended_log: "enable" + inspection_mode: "proxy" + log_all_url: "enable" + options: "js" + ovrd_perm: "bannedword-override" + post_action: "block" + web_content_log: "enable" + web_extended_all_action_log: "enable" + web_filter_activex_log: "enable" + web_filter_applet_log: "enable" + web_filter_command_block_log: "enable" + web_filter_cookie_log: "enable" + web_filter_cookie_removal_log: "enable" + web_filter_js_log: "enable" + web_filter_jscript_log: "enable" + web_filter_referer_log: "enable" + web_filter_unknown_log: "enable" + web_filter_vbs_log: "enable" + web_ftgd_err_log: "enable" + web_ftgd_quota_usage: "enable" + web_invalid_domain_log: "enable" + web_url_log: "enable" + wisp: "enable" + wisp_algorithm: "auto-learning" + youtube_channel_status: "blacklist" +''' + +RETURN = """ +api_result: + description: full API response, includes status code and message + returned: always + type: string +""" + +from ansible.module_utils.basic import AnsibleModule, env_fallback +from ansible.module_utils.network.fortimanager.fortimanager import AnsibleFortiManager + + +############### +# START METHODS +############### + + +def fmgr_webfilter_profile_addsetdelete(fmg, paramgram): + + mode = paramgram["mode"] + adom = paramgram["adom"] + + response = (-100000, {"msg": "Illegal or malformed paramgram discovered. System Exception"}) + url = "" + datagram = {} + + # EVAL THE MODE PARAMETER FOR SET OR ADD + if mode in ['set', 'add', 'update']: + url = '/pm/config/adom/{adom}/obj/webfilter/profile'.format(adom=adom) + datagram = fmgr_del_none(fmgr_prepare_dict(paramgram)) + + # EVAL THE MODE PARAMETER FOR DELETE + elif mode == "delete": + # SET THE CORRECT URL FOR DELETE + url = '/pm/config/adom/{adom}/obj/webfilter/profile/{name}'.format(adom=adom, name=paramgram["name"]) + datagram = {} + + # IF MODE = SET -- USE THE 'SET' API CALL MODE + if mode == "set": + response = fmg.set(url, datagram) + # IF MODE = UPDATE -- USER THE 'UPDATE' API CALL MODE + elif mode == "update": + response = fmg.update(url, datagram) + # IF MODE = ADD -- USE THE 'ADD' API CALL MODE + elif mode == "add": + response = fmg.add(url, datagram) + # IF MODE = DELETE -- USE THE DELETE URL AND API CALL MODE + elif mode == "delete": + response = fmg.delete(url, datagram) + + return response + + +# ADDITIONAL COMMON FUNCTIONS +def fmgr_logout(fmg, module, msg="NULL", results=(), good_codes=(0,), logout_on_fail=True, logout_on_success=False): + """ + THIS METHOD CONTROLS THE LOGOUT AND ERROR REPORTING AFTER AN METHOD OR FUNCTION RUNS + """ + # VALIDATION ERROR (NO RESULTS, JUST AN EXIT) + if msg != "NULL" and len(results) == 0: + try: + fmg.logout() + except: + pass + module.fail_json(msg=msg) + + # SUBMISSION ERROR + if len(results) > 0: + if msg == "NULL": + try: + msg = results[1]['status']['message'] + except: + msg = "No status message returned from pyFMG. Possible that this was a GET with a tuple result." + + if results[0] not in good_codes: + if logout_on_fail: + fmg.logout() + module.fail_json(msg=msg, **results[1]) + else: + if logout_on_success: + fmg.logout() + module.exit_json(msg="API Called worked, but logout handler has been asked to logout on success", + **results[1]) + return msg + + +# FUNCTION/METHOD FOR CONVERTING CIDR TO A NETMASK +# DID NOT USE IP ADDRESS MODULE TO KEEP INCLUDES TO A MINIMUM +def fmgr_cidr_to_netmask(cidr): + cidr = int(cidr) + mask = (0xffffffff >> (32 - cidr)) << (32 - cidr) + return(str((0xff000000 & mask) >> 24) + '.' + + str((0x00ff0000 & mask) >> 16) + '.' + + str((0x0000ff00 & mask) >> 8) + '.' + + str((0x000000ff & mask))) + + +# utility function: removing keys wih value of None, nothing in playbook for that key +def fmgr_del_none(obj): + if isinstance(obj, dict): + return type(obj)((fmgr_del_none(k), fmgr_del_none(v)) + for k, v in obj.items() if k is not None and (v is not None and not fmgr_is_empty_dict(v))) + else: + return obj + + +# utility function: remove keys that are need for the logic but the FMG API won't accept them +def fmgr_prepare_dict(obj): + list_of_elems = ["mode", "adom", "host", "username", "password"] + if isinstance(obj, dict): + obj = dict((key, fmgr_prepare_dict(value)) for (key, value) in obj.items() if key not in list_of_elems) + return obj + + +def fmgr_is_empty_dict(obj): + return_val = False + if isinstance(obj, dict): + if len(obj) > 0: + for k, v in obj.items(): + if isinstance(v, dict): + if len(v) == 0: + return_val = True + elif len(v) > 0: + for k1, v1 in v.items(): + if v1 is None: + return_val = True + elif v1 is not None: + return_val = False + return return_val + elif v is None: + return_val = True + elif v is not None: + return_val = False + return return_val + elif len(obj) == 0: + return_val = True + + return return_val + + +def fmgr_split_comma_strings_into_lists(obj): + if isinstance(obj, dict): + if len(obj) > 0: + for k, v in obj.items(): + if isinstance(v, str): + new_list = list() + if "," in v: + new_items = v.split(",") + for item in new_items: + new_list.append(item.strip()) + obj[k] = new_list + + return obj + + +############# +# END METHODS +############# + + +def main(): + argument_spec = dict( + adom=dict(type="str", default="root"), + host=dict(required=True, type="str"), + password=dict(fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]), no_log=True, required=True), + username=dict(fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"]), no_log=True, required=True), + mode=dict(choices=["add", "set", "delete", "update"], type="str", default="add"), + + youtube_channel_status=dict(required=False, type="str", choices=["disable", "blacklist", "whitelist"]), + wisp_servers=dict(required=False, type="str"), + wisp_algorithm=dict(required=False, type="str", choices=["auto-learning", "primary-secondary", "round-robin"]), + wisp=dict(required=False, type="str", choices=["disable", "enable"]), + web_url_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_invalid_domain_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_ftgd_quota_usage=dict(required=False, type="str", choices=["disable", "enable"]), + web_ftgd_err_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_vbs_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_unknown_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_referer_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_jscript_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_js_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_cookie_removal_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_cookie_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_command_block_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_applet_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_filter_activex_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_extended_all_action_log=dict(required=False, type="str", choices=["disable", "enable"]), + web_content_log=dict(required=False, type="str", choices=["disable", "enable"]), + replacemsg_group=dict(required=False, type="str"), + post_action=dict(required=False, type="str", choices=["normal", "block"]), + ovrd_perm=dict(required=False, type="list", choices=["bannedword-override", + "urlfilter-override", + "fortiguard-wf-override", + "contenttype-check-override"]), + options=dict(required=False, type="list", choices=["block-invalid-url", + "jscript", + "js", + "vbs", + "unknown", + "wf-referer", + "intrinsic", + "wf-cookie", + "per-user-bwl", + "activexfilter", + "cookiefilter", + "javafilter"]), + name=dict(required=False, type="str"), + log_all_url=dict(required=False, type="str", choices=["disable", "enable"]), + inspection_mode=dict(required=False, type="str", choices=["proxy", "flow-based"]), + https_replacemsg=dict(required=False, type="str", choices=["disable", "enable"]), + extended_log=dict(required=False, type="str", choices=["disable", "enable"]), + comment=dict(required=False, type="str"), + ftgd_wf=dict(required=False, type="list"), + ftgd_wf_exempt_quota=dict(required=False, type="str"), + ftgd_wf_max_quota_timeout=dict(required=False, type="int"), + ftgd_wf_options=dict(required=False, type="str", choices=["error-allow", "rate-server-ip", + "connect-request-bypass", "ftgd-disable"]), + ftgd_wf_ovrd=dict(required=False, type="str"), + ftgd_wf_rate_crl_urls=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_rate_css_urls=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_rate_image_urls=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_rate_javascript_urls=dict(required=False, type="str", choices=["disable", "enable"]), + + ftgd_wf_filters_action=dict(required=False, type="str", choices=["block", "monitor", + "warning", "authenticate"]), + ftgd_wf_filters_auth_usr_grp=dict(required=False, type="str"), + ftgd_wf_filters_category=dict(required=False, type="str"), + ftgd_wf_filters_log=dict(required=False, type="str", choices=["disable", "enable"]), + ftgd_wf_filters_override_replacemsg=dict(required=False, type="str"), + ftgd_wf_filters_warn_duration=dict(required=False, type="str"), + ftgd_wf_filters_warning_duration_type=dict(required=False, type="str", choices=["session", "timeout"]), + ftgd_wf_filters_warning_prompt=dict(required=False, type="str", choices=["per-domain", "per-category"]), + + ftgd_wf_quota_category=dict(required=False, type="str"), + ftgd_wf_quota_duration=dict(required=False, type="str"), + ftgd_wf_quota_override_replacemsg=dict(required=False, type="str"), + ftgd_wf_quota_type=dict(required=False, type="str", choices=["time", "traffic"]), + ftgd_wf_quota_unit=dict(required=False, type="str", choices=["B", "KB", "MB", "GB"]), + ftgd_wf_quota_value=dict(required=False, type="int"), + override=dict(required=False, type="list"), + override_ovrd_cookie=dict(required=False, type="str", choices=["deny", "allow"]), + override_ovrd_dur=dict(required=False, type="str"), + override_ovrd_dur_mode=dict(required=False, type="str", choices=["constant", "ask"]), + override_ovrd_scope=dict(required=False, type="str", choices=["user", "user-group", "ip", "ask", "browser"]), + override_ovrd_user_group=dict(required=False, type="str"), + override_profile=dict(required=False, type="str"), + override_profile_attribute=dict(required=False, type="list", choices=["User-Name", + "NAS-IP-Address", + "Framed-IP-Address", + "Framed-IP-Netmask", + "Filter-Id", + "Login-IP-Host", + "Reply-Message", + "Callback-Number", + "Callback-Id", + "Framed-Route", + "Framed-IPX-Network", + "Class", + "Called-Station-Id", + "Calling-Station-Id", + "NAS-Identifier", + "Proxy-State", + "Login-LAT-Service", + "Login-LAT-Node", + "Login-LAT-Group", + "Framed-AppleTalk-Zone", + "Acct-Session-Id", + "Acct-Multi-Session-Id"]), + override_profile_type=dict(required=False, type="str", choices=["list", "radius"]), + url_extraction=dict(required=False, type="list"), + url_extraction_redirect_header=dict(required=False, type="str"), + url_extraction_redirect_no_content=dict(required=False, type="str", choices=["disable", "enable"]), + url_extraction_redirect_url=dict(required=False, type="str"), + url_extraction_server_fqdn=dict(required=False, type="str"), + url_extraction_status=dict(required=False, type="str", choices=["disable", "enable"]), + web=dict(required=False, type="list"), + web_blacklist=dict(required=False, type="str", choices=["disable", "enable"]), + web_bword_table=dict(required=False, type="str"), + web_bword_threshold=dict(required=False, type="int"), + web_content_header_list=dict(required=False, type="str"), + web_keyword_match=dict(required=False, type="str"), + web_log_search=dict(required=False, type="str", choices=["disable", "enable"]), + web_safe_search=dict(required=False, type="str", choices=["url", "header"]), + web_urlfilter_table=dict(required=False, type="str"), + web_whitelist=dict(required=False, type="list", choices=["exempt-av", + "exempt-webcontent", + "exempt-activex-java-cookie", + "exempt-dlp", + "exempt-rangeblock", + "extended-log-others"]), + web_youtube_restrict=dict(required=False, type="str", choices=["strict", "none", "moderate"]), + youtube_channel_filter=dict(required=False, type="list"), + youtube_channel_filter_channel_id=dict(required=False, type="str"), + youtube_channel_filter_comment=dict(required=False, type="str"), + + ) + + module = AnsibleModule(argument_spec, supports_check_mode=False) + + # MODULE PARAMGRAM + paramgram = { + "mode": module.params["mode"], + "adom": module.params["adom"], + "youtube-channel-status": module.params["youtube_channel_status"], + "wisp-servers": module.params["wisp_servers"], + "wisp-algorithm": module.params["wisp_algorithm"], + "wisp": module.params["wisp"], + "web-url-log": module.params["web_url_log"], + "web-invalid-domain-log": module.params["web_invalid_domain_log"], + "web-ftgd-quota-usage": module.params["web_ftgd_quota_usage"], + "web-ftgd-err-log": module.params["web_ftgd_err_log"], + "web-filter-vbs-log": module.params["web_filter_vbs_log"], + "web-filter-unknown-log": module.params["web_filter_unknown_log"], + "web-filter-referer-log": module.params["web_filter_referer_log"], + "web-filter-jscript-log": module.params["web_filter_jscript_log"], + "web-filter-js-log": module.params["web_filter_js_log"], + "web-filter-cookie-removal-log": module.params["web_filter_cookie_removal_log"], + "web-filter-cookie-log": module.params["web_filter_cookie_log"], + "web-filter-command-block-log": module.params["web_filter_command_block_log"], + "web-filter-applet-log": module.params["web_filter_applet_log"], + "web-filter-activex-log": module.params["web_filter_activex_log"], + "web-extended-all-action-log": module.params["web_extended_all_action_log"], + "web-content-log": module.params["web_content_log"], + "replacemsg-group": module.params["replacemsg_group"], + "post-action": module.params["post_action"], + "ovrd-perm": module.params["ovrd_perm"], + "options": module.params["options"], + "name": module.params["name"], + "log-all-url": module.params["log_all_url"], + "inspection-mode": module.params["inspection_mode"], + "https-replacemsg": module.params["https_replacemsg"], + "extended-log": module.params["extended_log"], + "comment": module.params["comment"], + "ftgd-wf": { + "exempt-quota": module.params["ftgd_wf_exempt_quota"], + "max-quota-timeout": module.params["ftgd_wf_max_quota_timeout"], + "options": module.params["ftgd_wf_options"], + "ovrd": module.params["ftgd_wf_ovrd"], + "rate-crl-urls": module.params["ftgd_wf_rate_crl_urls"], + "rate-css-urls": module.params["ftgd_wf_rate_css_urls"], + "rate-image-urls": module.params["ftgd_wf_rate_image_urls"], + "rate-javascript-urls": module.params["ftgd_wf_rate_javascript_urls"], + "filters": { + "action": module.params["ftgd_wf_filters_action"], + "auth-usr-grp": module.params["ftgd_wf_filters_auth_usr_grp"], + "category": module.params["ftgd_wf_filters_category"], + "log": module.params["ftgd_wf_filters_log"], + "override-replacemsg": module.params["ftgd_wf_filters_override_replacemsg"], + "warn-duration": module.params["ftgd_wf_filters_warn_duration"], + "warning-duration-type": module.params["ftgd_wf_filters_warning_duration_type"], + "warning-prompt": module.params["ftgd_wf_filters_warning_prompt"], + }, + "quota": { + "category": module.params["ftgd_wf_quota_category"], + "duration": module.params["ftgd_wf_quota_duration"], + "override-replacemsg": module.params["ftgd_wf_quota_override_replacemsg"], + "type": module.params["ftgd_wf_quota_type"], + "unit": module.params["ftgd_wf_quota_unit"], + "value": module.params["ftgd_wf_quota_value"], + }, + }, + "override": { + "ovrd-cookie": module.params["override_ovrd_cookie"], + "ovrd-dur": module.params["override_ovrd_dur"], + "ovrd-dur-mode": module.params["override_ovrd_dur_mode"], + "ovrd-scope": module.params["override_ovrd_scope"], + "ovrd-user-group": module.params["override_ovrd_user_group"], + "profile": module.params["override_profile"], + "profile-attribute": module.params["override_profile_attribute"], + "profile-type": module.params["override_profile_type"], + }, + "url-extraction": { + "redirect-header": module.params["url_extraction_redirect_header"], + "redirect-no-content": module.params["url_extraction_redirect_no_content"], + "redirect-url": module.params["url_extraction_redirect_url"], + "server-fqdn": module.params["url_extraction_server_fqdn"], + "status": module.params["url_extraction_status"], + }, + "web": { + "blacklist": module.params["web_blacklist"], + "bword-table": module.params["web_bword_table"], + "bword-threshold": module.params["web_bword_threshold"], + "content-header-list": module.params["web_content_header_list"], + "keyword-match": module.params["web_keyword_match"], + "log-search": module.params["web_log_search"], + "safe-search": module.params["web_safe_search"], + "urlfilter-table": module.params["web_urlfilter_table"], + "whitelist": module.params["web_whitelist"], + "youtube-restrict": module.params["web_youtube_restrict"], + }, + "youtube-channel-filter": { + "channel-id": module.params["youtube_channel_filter_channel_id"], + "comment": module.params["youtube_channel_filter_comment"], + } + } + + list_overrides = ['ftgd-wf', 'override', 'url-extraction', 'web', 'youtube-channel-filter'] + for list_variable in list_overrides: + override_data = list() + try: + override_data = module.params[list_variable] + except: + pass + try: + if override_data: + del paramgram[list_variable] + paramgram[list_variable] = override_data + except: + pass + + # CHECK IF THE HOST/USERNAME/PW EXISTS, AND IF IT DOES, LOGIN. + host = module.params["host"] + password = module.params["password"] + username = module.params["username"] + if host is None or username is None or password is None: + module.fail_json(msg="Host and username and password are required") + + # CHECK IF LOGIN FAILED + fmg = AnsibleFortiManager(module, module.params["host"], module.params["username"], module.params["password"]) + + response = fmg.login() + if response[1]['status']['code'] != 0: + module.fail_json(msg="Connection to FortiManager Failed") + + results = fmgr_webfilter_profile_addsetdelete(fmg, paramgram) + if results[0] != 0: + fmgr_logout(fmg, module, results=results, good_codes=[0]) + + fmg.logout() + + if results is not None: + return module.exit_json(**results[1]) + else: + return module.exit_json(msg="No results were returned from the API call.") + + +if __name__ == "__main__": + main() diff --git a/test/units/modules/network/fortimanager/fixtures/test_fmgr_secprof_web.json b/test/units/modules/network/fortimanager/fixtures/test_fmgr_secprof_web.json new file mode 100644 index 00000000000..cc7b1ee2a70 --- /dev/null +++ b/test/units/modules/network/fortimanager/fixtures/test_fmgr_secprof_web.json @@ -0,0 +1,214 @@ +{ + "fmgr_webfilter_profile_addsetdelete": [ + { + "paramgram_used": { + "comment": null, + "web-extended-all-action-log": null, + "url-extraction": { + "status": null, + "redirect-url": null, + "server-fqdn": null, + "redirect-header": null, + "redirect-no-content": null + }, + "ftgd-wf": { + "filters": { + "category": null, + "log": null, + "override-replacemsg": null, + "warning-duration-type": null, + "warn-duration": null, + "auth-usr-grp": null, + "action": null, + "warning-prompt": null + }, + "ovrd": null, + "rate-image-urls": null, + "quota": { + "category": null, + "value": null, + "override-replacemsg": null, + "duration": null, + "type": null, + "unit": null + }, + "options": null, + "rate-javascript-urls": null, + "max-quota-timeout": null, + "rate-css-urls": null, + "exempt-quota": null, + "rate-crl-urls": null + }, + "log-all-url": null, + "extended-log": null, + "web-filter-cookie-removal-log": null, + "https-replacemsg": null, + "web": { + "log-search": null, + "bword-threshold": null, + "bword-table": null, + "whitelist": null, + "youtube-restrict": null, + "safe-search": null, + "blacklist": null, + "keyword-match": null, + "urlfilter-table": null, + "content-header-list": null + }, + "wisp": null, + "web-filter-vbs-log": null, + "youtube-channel-filter": { + "comment": null, + "channel-id": null + }, + "override": { + "profile": null, + "ovrd-scope": null, + "ovrd-dur-mode": null, + "profile-attribute": null, + "ovrd-dur": null, + "profile-type": null, + "ovrd-user-group": null, + "ovrd-cookie": null + }, + "ovrd-perm": null, + "mode": "delete", + "web-content-log": null, + "web-invalid-domain-log": null, + "adom": "root", + "web-filter-referer-log": null, + "inspection-mode": null, + "post-action": null, + "name": "Ansible_Web_Filter_Profile", + "web-filter-command-block-log": null, + "web-filter-applet-log": null, + "web-ftgd-err-log": null, + "replacemsg-group": null, + "web-filter-jscript-log": null, + "web-filter-activex-log": null, + "web-filter-js-log": null, + "web-ftgd-quota-usage": null, + "web-filter-unknown-log": null, + "web-filter-cookie-log": null, + "youtube-channel-status": null, + "web-url-log": null, + "options": null, + "wisp-servers": null, + "wisp-algorithm": null + }, + "raw_response": { + "status": { + "message": "OK", + "code": 0 + }, + "url": "/pm/config/adom/root/obj/webfilter/profile/Ansible_Web_Filter_Profile" + }, + "post_method": "delete" + }, + { + "raw_response": { + "status": { + "message": "OK", + "code": 0 + }, + "url": "/pm/config/adom/root/obj/webfilter/profile" + }, + "paramgram_used": { + "comment": "Created by Ansible Module TEST", + "web-filter-command-block-log": "enable", + "web-invalid-domain-log": "enable", + "web-extended-all-action-log": "enable", + "adom": "root", + "ftgd-wf": { + "rate-javascript-urls": null, + "quota": { + "category": null, + "value": null, + "override-replacemsg": null, + "duration": null, + "type": null, + "unit": null + }, + "rate-image-urls": null, + "filters": { + "category": null, + "auth-usr-grp": null, + "log": null, + "warning-prompt": null, + "override-replacemsg": null, + "action": null, + "warn-duration": null, + "warning-duration-type": null + }, + "rate-css-urls": null, + "ovrd": null, + "exempt-quota": null, + "max-quota-timeout": null, + "rate-crl-urls": null, + "options": null + }, + "web-content-log": "enable", + "web-filter-referer-log": "enable", + "log-all-url": "enable", + "extended-log": "enable", + "inspection-mode": "proxy", + "web-filter-cookie-removal-log": "enable", + "post-action": "block", + "web-filter-activex-log": "enable", + "web-filter-cookie-log": "enable", + "web": { + "blacklist": null, + "log-search": null, + "keyword-match": null, + "urlfilter-table": null, + "bword-table": null, + "safe-search": null, + "whitelist": null, + "content-header-list": null, + "youtube-restrict": null, + "bword-threshold": null + }, + "web-filter-applet-log": "enable", + "web-ftgd-err-log": "enable", + "replacemsg-group": null, + "web-filter-jscript-log": "enable", + "web-ftgd-quota-usage": "enable", + "url-extraction": { + "status": null, + "server-fqdn": null, + "redirect-url": null, + "redirect-header": null, + "redirect-no-content": null + }, + "web-filter-js-log": "enable", + "youtube-channel-filter": { + "comment": null, + "channel-id": null + }, + "name": "Ansible_Web_Filter_Profile", + "wisp": "enable", + "web-filter-vbs-log": "enable", + "web-filter-unknown-log": "enable", + "mode": "set", + "youtube-channel-status": "blacklist", + "override": { + "profile": null, + "ovrd-user-group": null, + "ovrd-scope": null, + "ovrd-cookie": null, + "ovrd-dur-mode": null, + "profile-attribute": null, + "ovrd-dur": null, + "profile-type": null + }, + "web-url-log": "enable", + "ovrd-perm": "bannedword-override", + "https-replacemsg": null, + "options": "js", + "wisp-servers": null, + "wisp-algorithm": "auto-learning" + }, + "post_method": "set" + } + ] +} diff --git a/test/units/modules/network/fortimanager/test_fmgr_secprof_web.py b/test/units/modules/network/fortimanager/test_fmgr_secprof_web.py new file mode 100644 index 00000000000..63fb85c0a46 --- /dev/null +++ b/test/units/modules/network/fortimanager/test_fmgr_secprof_web.py @@ -0,0 +1,157 @@ +# Copyright 2018 Fortinet, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os +import json +from pyFMG.fortimgr import FortiManager +import pytest + +try: + from ansible.modules.network.fortimanager import fmgr_secprof_web +except ImportError: + pytest.skip("Could not load required modules for testing", allow_module_level=True) + +fmg_instance = FortiManager("1.1.1.1", "admin", "") + + +def load_fixtures(): + fixture_path = os.path.join( + os.path.dirname(__file__), + 'fixtures') + "/{filename}.json".format( + filename=os.path.splitext( + os.path.basename(__file__))[0]) + try: + with open(fixture_path, "r") as fixture_file: + fixture_data = json.load(fixture_file) + except IOError: + return [] + return [fixture_data] + + +@pytest.fixture(scope="function", params=load_fixtures()) +def fixture_data(request): + func_name = request.function.__name__.replace("test_", "") + return request.param.get(func_name, None) + + +def test_fmgr_webfilter_profile_addsetdelete(fixture_data, mocker): + mocker.patch("pyFMG.fortimgr.FortiManager._post_request", side_effect=fixture_data) + # Fixture sets used:########################### + + ################################################## + # comment: None + # web-extended-all-action-log: None + # url-extraction: {'status': None, 'redirect-url': None, 'server-fqdn': None, 'redirect-header': None, + # 'redirect-no-content': None} + # ftgd-wf: {'filters': {'category': None, 'log': None, 'override-replacemsg': None, 'warning-duration-type': None, + # 'warn-duration': None, 'auth-usr-grp': None, 'action': None, 'warning-prompt': None}, 'ovrd': None, + # 'rate-image-urls': None, 'quota': {'category': None, 'value': None, 'override-replacemsg': None, + # 'duration': None, 'type': None, 'unit': None}, 'options': None, 'rate-javascript-urls': None, + # 'max-quota-timeout': None, 'rate-css-urls': None, 'exempt-quota': None, 'rate-crl-urls': None} + # log-all-url: None + # extended-log: None + # web-filter-cookie-removal-log: None + # https-replacemsg: None + # web: {'log-search': None, 'bword-threshold': None, 'bword-table': None, 'whitelist': None, + # 'youtube-restrict': None, 'safe-search': None, 'blacklist': None, 'keyword-match': None, + # 'urlfilter-table': None, 'content-header-list': None} + # wisp: None + # web-filter-vbs-log: None + # youtube-channel-filter: {'comment': None, 'channel-id': None} + # override: {'profile': None, 'ovrd-scope': None, 'ovrd-dur-mode': None, 'profile-attribute': None, + # 'ovrd-dur': None, 'profile-type': None, 'ovrd-user-group': None, 'ovrd-cookie': None} + # ovrd-perm: None + # mode: delete + # web-content-log: None + # web-invalid-domain-log: None + # adom: root + # web-filter-referer-log: None + # inspection-mode: None + # post-action: None + # name: Ansible_Web_Filter_Profile + # web-filter-command-block-log: None + # web-filter-applet-log: None + # web-ftgd-err-log: None + # replacemsg-group: None + # web-filter-jscript-log: None + # web-filter-activex-log: None + # web-filter-js-log: None + # web-ftgd-quota-usage: None + # web-filter-unknown-log: None + # web-filter-cookie-log: None + # youtube-channel-status: None + # web-url-log: None + # options: None + # wisp-servers: None + # wisp-algorithm: None + ################################################## + ################################################## + # comment: Created by Ansible Module TEST + # web-filter-command-block-log: enable + # web-invalid-domain-log: enable + # web-extended-all-action-log: enable + # adom: root + # ftgd-wf: {'rate-javascript-urls': None, 'quota': {'category': None, 'value': None, 'override-replacemsg': None, + # 'duration': None, 'type': None, 'unit': None}, 'rate-image-urls': None, 'filters': {'category': None, + # 'auth-usr-grp': None, 'log': None, 'warning-prompt': None, 'override-replacemsg': None, 'action': None, + # 'warn-duration': None, 'warning-duration-type': None}, 'rate-css-urls': None, 'ovrd': None, + # 'exempt-quota': None, 'max-quota-timeout': None, 'rate-crl-urls': None, 'options': None} + # web-content-log: enable + # web-filter-referer-log: enable + # log-all-url: enable + # extended-log: enable + # inspection-mode: proxy + # web-filter-cookie-removal-log: enable + # post-action: block + # web-filter-activex-log: enable + # web-filter-cookie-log: enable + # web: {'blacklist': None, 'log-search': None, 'keyword-match': None, 'urlfilter-table': None, 'bword-table': None, + # 'safe-search': None, 'whitelist': None, 'content-header-list': None, 'youtube-restrict': None, + # 'bword-threshold': None} + # web-filter-applet-log: enable + # web-ftgd-err-log: enable + # replacemsg-group: None + # web-filter-jscript-log: enable + # web-ftgd-quota-usage: enable + # url-extraction: {'status': None, 'server-fqdn': None, 'redirect-url': None, 'redirect-header': None, + # 'redirect-no-content': None} + # web-filter-js-log: enable + # youtube-channel-filter: {'comment': None, 'channel-id': None} + # name: Ansible_Web_Filter_Profile + # wisp: enable + # web-filter-vbs-log: enable + # web-filter-unknown-log: enable + # mode: set + # youtube-channel-status: blacklist + # override: {'profile': None, 'ovrd-user-group': None, 'ovrd-scope': None, 'ovrd-cookie': None, + # 'ovrd-dur-mode': None, 'profile-attribute': None, 'ovrd-dur': None, 'profile-type': None} + # web-url-log: enable + # ovrd-perm: bannedword-override + # https-replacemsg: None + # options: js + # wisp-servers: None + # wisp-algorithm: auto-learning + ################################################## + + # Test using fixture 1 # + output = fmgr_secprof_web.fmgr_webfilter_profile_addsetdelete(fmg_instance, fixture_data[0]['paramgram_used']) + assert output['raw_response']['status']['code'] == 0 + # Test using fixture 2 # + output = fmgr_secprof_web.fmgr_webfilter_profile_addsetdelete(fmg_instance, fixture_data[1]['paramgram_used']) + assert output['raw_response']['status']['code'] == 0