FortiOS modules for 2.9 - 4 (#60806)

* FortiOS modules for 2.9 - 4

* Update ignore.txt

* Updates from maintainers to legacy modules

* Update fortios_firewall_ssl_setting.py

* Update fortios_firewall_ssl_server.py
pull/60963/head
Miguel Angel Muñoz González 5 years ago committed by Nilashish Chakraborty
parent 2b103a2e54
commit 3cd70f53cc

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_proxy_address module: fortios_firewall_proxy_address
short_description: Web proxy address configuration in Fortinet's FortiOS and FortiGate. short_description: Web proxy address configuration in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and proxy_address category. user to set and modify firewall feature and proxy_address category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,95 +41,123 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip address. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_proxy_address: firewall_proxy_address:
description: description:
- Web proxy address configuration. - Web proxy address configuration.
default: null default: null
type: dict
suboptions: suboptions:
state: case_sensitivity:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
case-sensitivity:
description: description:
- Enable to make the pattern case sensitive. - Enable to make the pattern case sensitive.
type: str
choices: choices:
- disable - disable
- enable - enable
category: category:
description: description:
- FortiGuard category ID. - FortiGuard category ID.
type: list
suboptions: suboptions:
id: id:
description: description:
- Fortiguard category id. - Fortiguard category id.
required: true required: true
type: int
color: color:
description: description:
- Integer value to determine the color of the icon in the GUI (1 - 32, default = 0, which sets value to 1). - Integer value to determine the color of the icon in the GUI (1 - 32, default = 0, which sets value to 1).
type: int
comment: comment:
description: description:
- Optional comments. - Optional comments.
type: str
header: header:
description: description:
- HTTP header name as a regular expression. - HTTP header name as a regular expression.
header-group: type: str
header_group:
description: description:
- HTTP header group. - HTTP header group.
type: list
suboptions: suboptions:
case-sensitivity: case_sensitivity:
description: description:
- Case sensitivity in pattern. - Case sensitivity in pattern.
type: str
choices: choices:
- disable - disable
- enable - enable
header: header:
description: description:
- HTTP header regular expression. - HTTP header regular expression.
header-name: type: str
header_name:
description: description:
- HTTP header. - HTTP header.
type: str
id: id:
description: description:
- ID. - ID.
required: true required: true
header-name: type: int
header_name:
description: description:
- Name of HTTP header. - Name of HTTP header.
type: str
host: host:
description: description:
- Address object for the host. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name. - Address object for the host. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name.
host-regex: type: str
host_regex:
description: description:
- Host name as a regular expression. - Host name as a regular expression.
type: str
method: method:
description: description:
- HTTP request methods to be used. - HTTP request methods to be used.
type: str
choices: choices:
- get - get
- post - post
@ -146,40 +171,50 @@ options:
description: description:
- Address name. - Address name.
required: true required: true
type: str
path: path:
description: description:
- URL path as a regular expression. - URL path as a regular expression.
type: str
query: query:
description: description:
- Match the query part of the URL as a regular expression. - Match the query part of the URL as a regular expression.
type: str
referrer: referrer:
description: description:
- Enable/disable use of referrer field in the HTTP header to match the address. - Enable/disable use of referrer field in the HTTP header to match the address.
type: str
choices: choices:
- enable - enable
- disable - disable
tagging: tagging:
description: description:
- Config object tagging. - Config object tagging.
type: list
suboptions: suboptions:
category: category:
description: description:
- Tag category. Source system.object-tagging.category. - Tag category. Source system.object-tagging.category.
type: str
name: name:
description: description:
- Tagging entry name. - Tagging entry name.
required: true required: true
type: str
tags: tags:
description: description:
- Tags. - Tags.
type: list
suboptions: suboptions:
name: name:
description: description:
- Tag name. Source system.object-tagging.tags.name. - Tag name. Source system.object-tagging.tags.name.
required: true required: true
type: str
type: type:
description: description:
- Proxy address type. - Proxy address type.
type: str
choices: choices:
- host-regex - host-regex
- url - url
@ -192,6 +227,7 @@ options:
ua: ua:
description: description:
- Names of browsers to be used as user agent. - Names of browsers to be used as user agent.
type: str
choices: choices:
- chrome - chrome
- ms - ms
@ -201,9 +237,11 @@ options:
uuid: uuid:
description: description:
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset). - Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
type: str
visibility: visibility:
description: description:
- Enable/disable visibility of the object in the GUI. - Enable/disable visibility of the object in the GUI.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -216,6 +254,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Web proxy address configuration. - name: Web proxy address configuration.
fortios_firewall_proxy_address: fortios_firewall_proxy_address:
@ -224,24 +263,24 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_proxy_address: firewall_proxy_address:
state: "present" case_sensitivity: "disable"
case-sensitivity: "disable"
category: category:
- -
id: "5" id: "5"
color: "6" color: "6"
comment: "Optional comments." comment: "Optional comments."
header: "<your_own_value>" header: "<your_own_value>"
header-group: header_group:
- -
case-sensitivity: "disable" case_sensitivity: "disable"
header: "<your_own_value>" header: "<your_own_value>"
header-name: "<your_own_value>" header_name: "<your_own_value>"
id: "13" id: "13"
header-name: "<your_own_value>" header_name: "<your_own_value>"
host: "myhostname (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name)" host: "myhostname (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name)"
host-regex: "myhostname" host_regex: "myhostname"
method: "get" method: "get"
name: "default_name_18" name: "default_name_18"
path: "<your_own_value>" path: "<your_own_value>"
@ -320,14 +359,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -335,13 +376,13 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_proxy_address_data(json): def filter_firewall_proxy_address_data(json):
option_list = ['case-sensitivity', 'category', 'color', option_list = ['case_sensitivity', 'category', 'color',
'comment', 'header', 'header-group', 'comment', 'header', 'header_group',
'header-name', 'host', 'host-regex', 'header_name', 'host', 'host_regex',
'method', 'name', 'path', 'method', 'name', 'path',
'query', 'referrer', 'tagging', 'query', 'referrer', 'tagging',
'type', 'ua', 'uuid', 'type', 'ua', 'uuid',
@ -355,49 +396,67 @@ def filter_firewall_proxy_address_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_proxy_address(data, fos): def firewall_proxy_address(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_proxy_address_data = data['firewall_proxy_address'] firewall_proxy_address_data = data['firewall_proxy_address']
filtered_data = filter_firewall_proxy_address_data(firewall_proxy_address_data) filtered_data = underscore_to_hyphen(filter_firewall_proxy_address_data(firewall_proxy_address_data))
if firewall_proxy_address_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'proxy-address', 'proxy-address',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_proxy_address_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'proxy-address', 'proxy-address',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_proxy_address'] if data['firewall_proxy_address']:
for method in methodlist: resp = firewall_proxy_address(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_proxy_address": { "firewall_proxy_address": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "case_sensitivity": {"required": False, "type": "str",
"choices": ["present", "absent"]},
"case-sensitivity": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"category": {"required": False, "type": "list", "category": {"required": False, "type": "list",
"options": { "options": {
@ -406,17 +465,17 @@ def main():
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"header": {"required": False, "type": "str"}, "header": {"required": False, "type": "str"},
"header-group": {"required": False, "type": "list", "header_group": {"required": False, "type": "list",
"options": { "options": {
"case-sensitivity": {"required": False, "type": "str", "case_sensitivity": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"header": {"required": False, "type": "str"}, "header": {"required": False, "type": "str"},
"header-name": {"required": False, "type": "str"}, "header_name": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"header-name": {"required": False, "type": "str"}, "header_name": {"required": False, "type": "str"},
"host": {"required": False, "type": "str"}, "host": {"required": False, "type": "str"},
"host-regex": {"required": False, "type": "str"}, "host_regex": {"required": False, "type": "str"},
"method": {"required": False, "type": "str", "method": {"required": False, "type": "str",
"choices": ["get", "post", "put", "choices": ["get", "post", "put",
"head", "connect", "trace", "head", "connect", "trace",
@ -452,15 +511,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_proxy_addrgrp module: fortios_firewall_proxy_addrgrp
short_description: Web proxy address group configuration in Fortinet's FortiOS and FortiGate. short_description: Web proxy address group configuration in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and proxy_addrgrp category. user to set and modify firewall feature and proxy_addrgrp category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,89 +41,115 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip address. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_proxy_addrgrp: firewall_proxy_addrgrp:
description: description:
- Web proxy address group configuration. - Web proxy address group configuration.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
color: color:
description: description:
- Integer value to determine the color of the icon in the GUI (1 - 32, default = 0, which sets value to 1). - Integer value to determine the color of the icon in the GUI (1 - 32, default = 0, which sets value to 1).
type: int
comment: comment:
description: description:
- Optional comments. - Optional comments.
type: str
member: member:
description: description:
- Members of address group. - Members of address group.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.proxy-address.name firewall.proxy-addrgrp.name. - Address name. Source firewall.proxy-address.name firewall.proxy-addrgrp.name.
required: true required: true
type: str
name: name:
description: description:
- Address group name. - Address group name.
required: true required: true
type: str
tagging: tagging:
description: description:
- Config object tagging. - Config object tagging.
type: list
suboptions: suboptions:
category: category:
description: description:
- Tag category. Source system.object-tagging.category. - Tag category. Source system.object-tagging.category.
type: str
name: name:
description: description:
- Tagging entry name. - Tagging entry name.
required: true required: true
type: str
tags: tags:
description: description:
- Tags. - Tags.
type: list
suboptions: suboptions:
name: name:
description: description:
- Tag name. Source system.object-tagging.tags.name. - Tag name. Source system.object-tagging.tags.name.
required: true required: true
type: str
type: type:
description: description:
- Source or destination address group type. - Source or destination address group type.
type: str
choices: choices:
- src - src
- dst - dst
uuid: uuid:
description: description:
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset). - Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
type: str
visibility: visibility:
description: description:
- Enable/disable visibility of the object in the GUI. - Enable/disable visibility of the object in the GUI.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -139,6 +162,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Web proxy address group configuration. - name: Web proxy address group configuration.
fortios_firewall_proxy_addrgrp: fortios_firewall_proxy_addrgrp:
@ -147,8 +171,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_proxy_addrgrp: firewall_proxy_addrgrp:
state: "present"
color: "3" color: "3"
comment: "Optional comments." comment: "Optional comments."
member: member:
@ -227,14 +251,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -242,7 +268,7 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_proxy_addrgrp_data(json): def filter_firewall_proxy_addrgrp_data(json):
@ -258,48 +284,66 @@ def filter_firewall_proxy_addrgrp_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_proxy_addrgrp(data, fos): def firewall_proxy_addrgrp(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_proxy_addrgrp_data = data['firewall_proxy_addrgrp'] firewall_proxy_addrgrp_data = data['firewall_proxy_addrgrp']
filtered_data = filter_firewall_proxy_addrgrp_data(firewall_proxy_addrgrp_data) filtered_data = underscore_to_hyphen(filter_firewall_proxy_addrgrp_data(firewall_proxy_addrgrp_data))
if firewall_proxy_addrgrp_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'proxy-addrgrp', 'proxy-addrgrp',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_proxy_addrgrp_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'proxy-addrgrp', 'proxy-addrgrp',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_proxy_addrgrp'] if data['firewall_proxy_addrgrp']:
for method in methodlist: resp = firewall_proxy_addrgrp(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_proxy_addrgrp": { "firewall_proxy_addrgrp": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"member": {"required": False, "type": "list", "member": {"required": False, "type": "list",
@ -328,15 +372,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_proxy_policy module: fortios_firewall_proxy_policy
short_description: Configure proxy policies in Fortinet's FortiOS and FortiGate. short_description: Configure proxy policies in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and proxy_policy category. user to set and modify firewall feature and proxy_policy category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,163 +41,204 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip address. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_proxy_policy: firewall_proxy_policy:
description: description:
- Configure proxy policies. - Configure proxy policies.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
action: action:
description: description:
- Accept or deny traffic matching the policy parameters. - Accept or deny traffic matching the policy parameters.
type: str
choices: choices:
- accept - accept
- deny - deny
- redirect - redirect
application-list: application_list:
description: description:
- Name of an existing Application list. Source application.list.name. - Name of an existing Application list. Source application.list.name.
av-profile: type: str
av_profile:
description: description:
- Name of an existing Antivirus profile. Source antivirus.profile.name. - Name of an existing Antivirus profile. Source antivirus.profile.name.
type: str
comments: comments:
description: description:
- Optional comments. - Optional comments.
type: str
disclaimer: disclaimer:
description: description:
- "Web proxy disclaimer setting: by domain, policy, or user." - "Web proxy disclaimer setting: by domain, policy, or user."
type: str
choices: choices:
- disable - disable
- domain - domain
- policy - policy
- user - user
dlp-sensor: dlp_sensor:
description: description:
- Name of an existing DLP sensor. Source dlp.sensor.name. - Name of an existing DLP sensor. Source dlp.sensor.name.
type: str
dstaddr: dstaddr:
description: description:
- Destination address objects. - Destination address objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name - Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name
firewall.vip.name firewall.vipgrp.name firewall.vip46.name firewall.vipgrp46.name system.external-resource.name. firewall.vip.name firewall.vipgrp.name firewall.vip46.name firewall.vipgrp46.name system.external-resource.name.
required: true required: true
dstaddr-negate: type: str
dstaddr_negate:
description: description:
- When enabled, destination addresses match against any address EXCEPT the specified destination addresses. - When enabled, destination addresses match against any address EXCEPT the specified destination addresses.
type: str
choices: choices:
- enable - enable
- disable - disable
dstaddr6: dstaddr6:
description: description:
- IPv6 destination address objects. - IPv6 destination address objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address6.name firewall.addrgrp6.name firewall.vip6.name firewall.vipgrp6.name firewall.vip64.name - Address name. Source firewall.address6.name firewall.addrgrp6.name firewall.vip6.name firewall.vipgrp6.name firewall.vip64.name
firewall.vipgrp64.name system.external-resource.name. firewall.vipgrp64.name system.external-resource.name.
required: true required: true
type: str
dstintf: dstintf:
description: description:
- Destination interface names. - Destination interface names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Interface name. Source system.interface.name system.zone.name. - Interface name. Source system.interface.name system.zone.name.
required: true required: true
global-label: type: str
global_label:
description: description:
- Global web-based manager visible label. - Global web-based manager visible label.
type: str
groups: groups:
description: description:
- Names of group objects. - Names of group objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Group name. Source user.group.name. - Group name. Source user.group.name.
required: true required: true
http-tunnel-auth: type: str
http_tunnel_auth:
description: description:
- Enable/disable HTTP tunnel authentication. - Enable/disable HTTP tunnel authentication.
type: str
choices: choices:
- enable - enable
- disable - disable
icap-profile: icap_profile:
description: description:
- Name of an existing ICAP profile. Source icap.profile.name. - Name of an existing ICAP profile. Source icap.profile.name.
internet-service: type: str
internet_service:
description: description:
- Enable/disable use of Internet Services for this policy. If enabled, destination address and service are not used. - Enable/disable use of Internet Services for this policy. If enabled, destination address and service are not used.
type: str
choices: choices:
- enable - enable
- disable - disable
internet-service-custom: internet_service_custom:
description: description:
- Custom Internet Service name. - Custom Internet Service name.
type: list
suboptions: suboptions:
name: name:
description: description:
- Custom name. Source firewall.internet-service-custom.name. - Custom name. Source firewall.internet-service-custom.name.
required: true required: true
internet-service-id: type: str
internet_service_id:
description: description:
- Internet Service ID. - Internet Service ID.
type: list
suboptions: suboptions:
id: id:
description: description:
- Internet Service ID. Source firewall.internet-service.id. - Internet Service ID. Source firewall.internet-service.id.
required: true required: true
internet-service-negate: type: int
internet_service_negate:
description: description:
- When enabled, Internet Services match against any internet service EXCEPT the selected Internet Service. - When enabled, Internet Services match against any internet service EXCEPT the selected Internet Service.
type: str
choices: choices:
- enable - enable
- disable - disable
ips-sensor: ips_sensor:
description: description:
- Name of an existing IPS sensor. Source ips.sensor.name. - Name of an existing IPS sensor. Source ips.sensor.name.
type: str
label: label:
description: description:
- VDOM-specific GUI visible label. - VDOM-specific GUI visible label.
type: str
logtraffic: logtraffic:
description: description:
- Enable/disable logging traffic through the policy. - Enable/disable logging traffic through the policy.
type: str
choices: choices:
- all - all
- utm - utm
- disable - disable
logtraffic-start: logtraffic_start:
description: description:
- Enable/disable policy log traffic start. - Enable/disable policy log traffic start.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -208,29 +246,36 @@ options:
description: description:
- Policy ID. - Policy ID.
required: true required: true
type: int
poolname: poolname:
description: description:
- Name of IP pool object. - Name of IP pool object.
type: list
suboptions: suboptions:
name: name:
description: description:
- IP pool name. Source firewall.ippool.name. - IP pool name. Source firewall.ippool.name.
required: true required: true
profile-group: type: str
profile_group:
description: description:
- Name of profile group. Source firewall.profile-group.name. - Name of profile group. Source firewall.profile-group.name.
profile-protocol-options: type: str
profile_protocol_options:
description: description:
- Name of an existing Protocol options profile. Source firewall.profile-protocol-options.name. - Name of an existing Protocol options profile. Source firewall.profile-protocol-options.name.
profile-type: type: str
profile_type:
description: description:
- Determine whether the firewall policy allows security profile groups or single profiles only. - Determine whether the firewall policy allows security profile groups or single profiles only.
type: str
choices: choices:
- single - single
- group - group
proxy: proxy:
description: description:
- Type of explicit proxy. - Type of explicit proxy.
type: str
choices: choices:
- explicit-web - explicit-web
- transparent-web - transparent-web
@ -238,15 +283,18 @@ options:
- ssh - ssh
- ssh-tunnel - ssh-tunnel
- wanopt - wanopt
redirect-url: redirect_url:
description: description:
- Redirect URL for further explicit web proxy processing. - Redirect URL for further explicit web proxy processing.
replacemsg-override-group: type: str
replacemsg_override_group:
description: description:
- Authentication replacement message override group. Source system.replacemsg-group.name. - Authentication replacement message override group. Source system.replacemsg-group.name.
scan-botnet-connections: type: str
scan_botnet_connections:
description: description:
- Enable/disable scanning of connections to Botnet servers. - Enable/disable scanning of connections to Botnet servers.
type: str
choices: choices:
- disable - disable
- block - block
@ -254,116 +302,143 @@ options:
schedule: schedule:
description: description:
- Name of schedule object. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name. - Name of schedule object. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name.
type: str
service: service:
description: description:
- Name of service objects. - Name of service objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Service name. Source firewall.service.custom.name firewall.service.group.name. - Service name. Source firewall.service.custom.name firewall.service.group.name.
required: true required: true
service-negate: type: str
service_negate:
description: description:
- When enabled, services match against any service EXCEPT the specified destination services. - When enabled, services match against any service EXCEPT the specified destination services.
type: str
choices: choices:
- enable - enable
- disable - disable
session-ttl: session_ttl:
description: description:
- TTL in seconds for sessions accepted by this policy (0 means use the system default session TTL). - TTL in seconds for sessions accepted by this policy (0 means use the system default session TTL).
spamfilter-profile: type: int
spamfilter_profile:
description: description:
- Name of an existing Spam filter profile. Source spamfilter.profile.name. - Name of an existing Spam filter profile. Source spamfilter.profile.name.
type: str
srcaddr: srcaddr:
description: description:
- Source address objects (must be set when using Web proxy). - Source address objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name system - Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name system
.external-resource.name. .external-resource.name.
required: true required: true
srcaddr-negate: type: str
srcaddr_negate:
description: description:
- When enabled, source addresses match against any address EXCEPT the specified source addresses. - When enabled, source addresses match against any address EXCEPT the specified source addresses.
type: str
choices: choices:
- enable - enable
- disable - disable
srcaddr6: srcaddr6:
description: description:
- IPv6 source address objects. - IPv6 source address objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address6.name firewall.addrgrp6.name system.external-resource.name. - Address name. Source firewall.address6.name firewall.addrgrp6.name system.external-resource.name.
required: true required: true
type: str
srcintf: srcintf:
description: description:
- Source interface names. - Source interface names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Interface name. Source system.interface.name system.zone.name. - Interface name. Source system.interface.name system.zone.name.
required: true required: true
ssh-filter-profile: type: str
ssh_filter_profile:
description: description:
- Name of an existing SSH filter profile. Source ssh-filter.profile.name. - Name of an existing SSH filter profile. Source ssh-filter.profile.name.
ssl-ssh-profile: type: str
ssl_ssh_profile:
description: description:
- Name of an existing SSL SSH profile. Source firewall.ssl-ssh-profile.name. - Name of an existing SSL SSH profile. Source firewall.ssl-ssh-profile.name.
type: str
status: status:
description: description:
- Enable/disable the active status of the policy. - Enable/disable the active status of the policy.
type: str
choices: choices:
- enable - enable
- disable - disable
transparent: transparent:
description: description:
- Enable to use the IP address of the client to connect to the server. - Enable to use the IP address of the client to connect to the server.
type: str
choices: choices:
- enable - enable
- disable - disable
users: users:
description: description:
- Names of user objects. - Names of user objects.
type: list
suboptions: suboptions:
name: name:
description: description:
- Group name. Source user.local.name. - Group name. Source user.local.name.
required: true required: true
utm-status: type: str
utm_status:
description: description:
- Enable the use of UTM profiles/sensors/lists. - Enable the use of UTM profiles/sensors/lists.
type: str
choices: choices:
- enable - enable
- disable - disable
uuid: uuid:
description: description:
- Universally Unique Identifier (UUID; automatically assigned but can be manually reset). - Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
waf-profile: type: str
waf_profile:
description: description:
- Name of an existing Web application firewall profile. Source waf.profile.name. - Name of an existing Web application firewall profile. Source waf.profile.name.
type: str
webcache: webcache:
description: description:
- Enable/disable web caching. - Enable/disable web caching.
type: str
choices: choices:
- enable - enable
- disable - disable
webcache-https: webcache_https:
description: description:
- Enable/disable web caching for HTTPS (Requires deep-inspection enabled in ssl-ssh-profile). - Enable/disable web caching for HTTPS (Requires deep-inspection enabled in ssl-ssh-profile).
type: str
choices: choices:
- disable - disable
- enable - enable
webfilter-profile: webfilter_profile:
description: description:
- Name of an existing Web filter profile. Source webfilter.profile.name. - Name of an existing Web filter profile. Source webfilter.profile.name.
webproxy-forward-server: type: str
webproxy_forward_server:
description: description:
- Name of web proxy forward server. Source web-proxy.forward-server.name web-proxy.forward-server-group.name. - Name of web proxy forward server. Source web-proxy.forward-server.name web-proxy.forward-server-group.name.
webproxy-profile: type: str
webproxy_profile:
description: description:
- Name of web proxy profile. Source web-proxy.profile.name. - Name of web proxy profile. Source web-proxy.profile.name.
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -373,6 +448,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure proxy policies. - name: Configure proxy policies.
fortios_firewall_proxy_policy: fortios_firewall_proxy_policy:
@ -381,19 +457,19 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_proxy_policy: firewall_proxy_policy:
state: "present"
action: "accept" action: "accept"
application-list: "<your_own_value> (source application.list.name)" application_list: "<your_own_value> (source application.list.name)"
av-profile: "<your_own_value> (source antivirus.profile.name)" av_profile: "<your_own_value> (source antivirus.profile.name)"
comments: "<your_own_value>" comments: "<your_own_value>"
disclaimer: "disable" disclaimer: "disable"
dlp-sensor: "<your_own_value> (source dlp.sensor.name)" dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
dstaddr: dstaddr:
- -
name: "default_name_10 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name firewall.vip name: "default_name_10 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name firewall.vip
.name firewall.vipgrp.name firewall.vip46.name firewall.vipgrp46.name system.external-resource.name)" .name firewall.vipgrp.name firewall.vip46.name firewall.vipgrp46.name system.external-resource.name)"
dstaddr-negate: "enable" dstaddr_negate: "enable"
dstaddr6: dstaddr6:
- -
name: "default_name_13 (source firewall.address6.name firewall.addrgrp6.name firewall.vip6.name firewall.vipgrp6.name firewall.vip64.name firewall name: "default_name_13 (source firewall.address6.name firewall.addrgrp6.name firewall.vip6.name firewall.vipgrp6.name firewall.vip64.name firewall
@ -401,68 +477,68 @@ EXAMPLES = '''
dstintf: dstintf:
- -
name: "default_name_15 (source system.interface.name system.zone.name)" name: "default_name_15 (source system.interface.name system.zone.name)"
global-label: "<your_own_value>" global_label: "<your_own_value>"
groups: groups:
- -
name: "default_name_18 (source user.group.name)" name: "default_name_18 (source user.group.name)"
http-tunnel-auth: "enable" http_tunnel_auth: "enable"
icap-profile: "<your_own_value> (source icap.profile.name)" icap_profile: "<your_own_value> (source icap.profile.name)"
internet-service: "enable" internet_service: "enable"
internet-service-custom: internet_service_custom:
- -
name: "default_name_23 (source firewall.internet-service-custom.name)" name: "default_name_23 (source firewall.internet-service-custom.name)"
internet-service-id: internet_service_id:
- -
id: "25 (source firewall.internet-service.id)" id: "25 (source firewall.internet-service.id)"
internet-service-negate: "enable" internet_service_negate: "enable"
ips-sensor: "<your_own_value> (source ips.sensor.name)" ips_sensor: "<your_own_value> (source ips.sensor.name)"
label: "<your_own_value>" label: "<your_own_value>"
logtraffic: "all" logtraffic: "all"
logtraffic-start: "enable" logtraffic_start: "enable"
policyid: "31" policyid: "31"
poolname: poolname:
- -
name: "default_name_33 (source firewall.ippool.name)" name: "default_name_33 (source firewall.ippool.name)"
profile-group: "<your_own_value> (source firewall.profile-group.name)" profile_group: "<your_own_value> (source firewall.profile-group.name)"
profile-protocol-options: "<your_own_value> (source firewall.profile-protocol-options.name)" profile_protocol_options: "<your_own_value> (source firewall.profile-protocol-options.name)"
profile-type: "single" profile_type: "single"
proxy: "explicit-web" proxy: "explicit-web"
redirect-url: "<your_own_value>" redirect_url: "<your_own_value>"
replacemsg-override-group: "<your_own_value> (source system.replacemsg-group.name)" replacemsg_override_group: "<your_own_value> (source system.replacemsg-group.name)"
scan-botnet-connections: "disable" scan_botnet_connections: "disable"
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)" schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
service: service:
- -
name: "default_name_43 (source firewall.service.custom.name firewall.service.group.name)" name: "default_name_43 (source firewall.service.custom.name firewall.service.group.name)"
service-negate: "enable" service_negate: "enable"
session-ttl: "45" session_ttl: "45"
spamfilter-profile: "<your_own_value> (source spamfilter.profile.name)" spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
srcaddr: srcaddr:
- -
name: "default_name_48 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name system name: "default_name_48 (source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name system
.external-resource.name)" .external-resource.name)"
srcaddr-negate: "enable" srcaddr_negate: "enable"
srcaddr6: srcaddr6:
- -
name: "default_name_51 (source firewall.address6.name firewall.addrgrp6.name system.external-resource.name)" name: "default_name_51 (source firewall.address6.name firewall.addrgrp6.name system.external-resource.name)"
srcintf: srcintf:
- -
name: "default_name_53 (source system.interface.name system.zone.name)" name: "default_name_53 (source system.interface.name system.zone.name)"
ssh-filter-profile: "<your_own_value> (source ssh-filter.profile.name)" ssh_filter_profile: "<your_own_value> (source ssh-filter.profile.name)"
ssl-ssh-profile: "<your_own_value> (source firewall.ssl-ssh-profile.name)" ssl_ssh_profile: "<your_own_value> (source firewall.ssl-ssh-profile.name)"
status: "enable" status: "enable"
transparent: "enable" transparent: "enable"
users: users:
- -
name: "default_name_59 (source user.local.name)" name: "default_name_59 (source user.local.name)"
utm-status: "enable" utm_status: "enable"
uuid: "<your_own_value>" uuid: "<your_own_value>"
waf-profile: "<your_own_value> (source waf.profile.name)" waf_profile: "<your_own_value> (source waf.profile.name)"
webcache: "enable" webcache: "enable"
webcache-https: "disable" webcache_https: "disable"
webfilter-profile: "<your_own_value> (source webfilter.profile.name)" webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
webproxy-forward-server: "<your_own_value> (source web-proxy.forward-server.name web-proxy.forward-server-group.name)" webproxy_forward_server: "<your_own_value> (source web-proxy.forward-server.name web-proxy.forward-server-group.name)"
webproxy-profile: "<your_own_value> (source web-proxy.profile.name)" webproxy_profile: "<your_own_value> (source web-proxy.profile.name)"
''' '''
RETURN = ''' RETURN = '''
@ -525,14 +601,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -540,28 +618,28 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_proxy_policy_data(json): def filter_firewall_proxy_policy_data(json):
option_list = ['action', 'application-list', 'av-profile', option_list = ['action', 'application_list', 'av_profile',
'comments', 'disclaimer', 'dlp-sensor', 'comments', 'disclaimer', 'dlp_sensor',
'dstaddr', 'dstaddr-negate', 'dstaddr6', 'dstaddr', 'dstaddr_negate', 'dstaddr6',
'dstintf', 'global-label', 'groups', 'dstintf', 'global_label', 'groups',
'http-tunnel-auth', 'icap-profile', 'internet-service', 'http_tunnel_auth', 'icap_profile', 'internet_service',
'internet-service-custom', 'internet-service-id', 'internet-service-negate', 'internet_service_custom', 'internet_service_id', 'internet_service_negate',
'ips-sensor', 'label', 'logtraffic', 'ips_sensor', 'label', 'logtraffic',
'logtraffic-start', 'policyid', 'poolname', 'logtraffic_start', 'policyid', 'poolname',
'profile-group', 'profile-protocol-options', 'profile-type', 'profile_group', 'profile_protocol_options', 'profile_type',
'proxy', 'redirect-url', 'replacemsg-override-group', 'proxy', 'redirect_url', 'replacemsg_override_group',
'scan-botnet-connections', 'schedule', 'service', 'scan_botnet_connections', 'schedule', 'service',
'service-negate', 'session-ttl', 'spamfilter-profile', 'service_negate', 'session_ttl', 'spamfilter_profile',
'srcaddr', 'srcaddr-negate', 'srcaddr6', 'srcaddr', 'srcaddr_negate', 'srcaddr6',
'srcintf', 'ssh-filter-profile', 'ssl-ssh-profile', 'srcintf', 'ssh_filter_profile', 'ssl_ssh_profile',
'status', 'transparent', 'users', 'status', 'transparent', 'users',
'utm-status', 'uuid', 'waf-profile', 'utm_status', 'uuid', 'waf_profile',
'webcache', 'webcache-https', 'webfilter-profile', 'webcache', 'webcache_https', 'webfilter_profile',
'webproxy-forward-server', 'webproxy-profile'] 'webproxy_forward_server', 'webproxy_profile']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -571,62 +649,80 @@ def filter_firewall_proxy_policy_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_proxy_policy(data, fos): def firewall_proxy_policy(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_proxy_policy_data = data['firewall_proxy_policy'] firewall_proxy_policy_data = data['firewall_proxy_policy']
filtered_data = filter_firewall_proxy_policy_data(firewall_proxy_policy_data) filtered_data = underscore_to_hyphen(filter_firewall_proxy_policy_data(firewall_proxy_policy_data))
if firewall_proxy_policy_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'proxy-policy', 'proxy-policy',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_proxy_policy_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'proxy-policy', 'proxy-policy',
mkey=filtered_data['policyid'], mkey=filtered_data['policyid'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_proxy_policy'] if data['firewall_proxy_policy']:
for method in methodlist: resp = firewall_proxy_policy(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_proxy_policy": { "firewall_proxy_policy": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"action": {"required": False, "type": "str", "action": {"required": False, "type": "str",
"choices": ["accept", "deny", "redirect"]}, "choices": ["accept", "deny", "redirect"]},
"application-list": {"required": False, "type": "str"}, "application_list": {"required": False, "type": "str"},
"av-profile": {"required": False, "type": "str"}, "av_profile": {"required": False, "type": "str"},
"comments": {"required": False, "type": "str"}, "comments": {"required": False, "type": "str"},
"disclaimer": {"required": False, "type": "str", "disclaimer": {"required": False, "type": "str",
"choices": ["disable", "domain", "policy", "choices": ["disable", "domain", "policy",
"user"]}, "user"]},
"dlp-sensor": {"required": False, "type": "str"}, "dlp_sensor": {"required": False, "type": "str"},
"dstaddr": {"required": False, "type": "list", "dstaddr": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"dstaddr-negate": {"required": False, "type": "str", "dstaddr_negate": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"dstaddr6": {"required": False, "type": "list", "dstaddr6": {"required": False, "type": "list",
"options": { "options": {
@ -636,62 +732,62 @@ def main():
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"global-label": {"required": False, "type": "str"}, "global_label": {"required": False, "type": "str"},
"groups": {"required": False, "type": "list", "groups": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"http-tunnel-auth": {"required": False, "type": "str", "http_tunnel_auth": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"icap-profile": {"required": False, "type": "str"}, "icap_profile": {"required": False, "type": "str"},
"internet-service": {"required": False, "type": "str", "internet_service": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"internet-service-custom": {"required": False, "type": "list", "internet_service_custom": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"internet-service-id": {"required": False, "type": "list", "internet_service_id": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"internet-service-negate": {"required": False, "type": "str", "internet_service_negate": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"ips-sensor": {"required": False, "type": "str"}, "ips_sensor": {"required": False, "type": "str"},
"label": {"required": False, "type": "str"}, "label": {"required": False, "type": "str"},
"logtraffic": {"required": False, "type": "str", "logtraffic": {"required": False, "type": "str",
"choices": ["all", "utm", "disable"]}, "choices": ["all", "utm", "disable"]},
"logtraffic-start": {"required": False, "type": "str", "logtraffic_start": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"policyid": {"required": True, "type": "int"}, "policyid": {"required": True, "type": "int"},
"poolname": {"required": False, "type": "list", "poolname": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"profile-group": {"required": False, "type": "str"}, "profile_group": {"required": False, "type": "str"},
"profile-protocol-options": {"required": False, "type": "str"}, "profile_protocol_options": {"required": False, "type": "str"},
"profile-type": {"required": False, "type": "str", "profile_type": {"required": False, "type": "str",
"choices": ["single", "group"]}, "choices": ["single", "group"]},
"proxy": {"required": False, "type": "str", "proxy": {"required": False, "type": "str",
"choices": ["explicit-web", "transparent-web", "ftp", "choices": ["explicit-web", "transparent-web", "ftp",
"ssh", "ssh-tunnel", "wanopt"]}, "ssh", "ssh-tunnel", "wanopt"]},
"redirect-url": {"required": False, "type": "str"}, "redirect_url": {"required": False, "type": "str"},
"replacemsg-override-group": {"required": False, "type": "str"}, "replacemsg_override_group": {"required": False, "type": "str"},
"scan-botnet-connections": {"required": False, "type": "str", "scan_botnet_connections": {"required": False, "type": "str",
"choices": ["disable", "block", "monitor"]}, "choices": ["disable", "block", "monitor"]},
"schedule": {"required": False, "type": "str"}, "schedule": {"required": False, "type": "str"},
"service": {"required": False, "type": "list", "service": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"service-negate": {"required": False, "type": "str", "service_negate": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"session-ttl": {"required": False, "type": "int"}, "session_ttl": {"required": False, "type": "int"},
"spamfilter-profile": {"required": False, "type": "str"}, "spamfilter_profile": {"required": False, "type": "str"},
"srcaddr": {"required": False, "type": "list", "srcaddr": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"srcaddr-negate": {"required": False, "type": "str", "srcaddr_negate": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"srcaddr6": {"required": False, "type": "list", "srcaddr6": {"required": False, "type": "list",
"options": { "options": {
@ -701,8 +797,8 @@ def main():
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"ssh-filter-profile": {"required": False, "type": "str"}, "ssh_filter_profile": {"required": False, "type": "str"},
"ssl-ssh-profile": {"required": False, "type": "str"}, "ssl_ssh_profile": {"required": False, "type": "str"},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"transparent": {"required": False, "type": "str", "transparent": {"required": False, "type": "str",
@ -711,17 +807,17 @@ def main():
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"utm-status": {"required": False, "type": "str", "utm_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"uuid": {"required": False, "type": "str"}, "uuid": {"required": False, "type": "str"},
"waf-profile": {"required": False, "type": "str"}, "waf_profile": {"required": False, "type": "str"},
"webcache": {"required": False, "type": "str", "webcache": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"webcache-https": {"required": False, "type": "str", "webcache_https": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"webfilter-profile": {"required": False, "type": "str"}, "webfilter_profile": {"required": False, "type": "str"},
"webproxy-forward-server": {"required": False, "type": "str"}, "webproxy_forward_server": {"required": False, "type": "str"},
"webproxy-profile": {"required": False, "type": "str"} "webproxy_profile": {"required": False, "type": "str"}
} }
} }
@ -729,15 +825,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_schedule_group module: fortios_firewall_schedule_group
short_description: Schedule group configuration in Fortinet's FortiOS and FortiGate. short_description: Schedule group configuration in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_schedule feature and group category. user to set and modify firewall_schedule feature and group category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,55 +41,72 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_schedule_group: firewall_schedule_group:
description: description:
- Schedule group configuration. - Schedule group configuration.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
color: color:
description: description:
- Color of icon on the GUI. - Color of icon on the GUI.
type: int
member: member:
description: description:
- Schedules added to the schedule group. - Schedules added to the schedule group.
type: list
suboptions: suboptions:
name: name:
description: description:
- Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name. - Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name.
required: true required: true
type: str
name: name:
description: description:
- Schedule group name. - Schedule group name.
required: true required: true
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -102,6 +116,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Schedule group configuration. - name: Schedule group configuration.
fortios_firewall_schedule_group: fortios_firewall_schedule_group:
@ -110,8 +125,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_schedule_group: firewall_schedule_group:
state: "present"
color: "3" color: "3"
member: member:
- -
@ -179,14 +194,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -194,7 +211,7 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_schedule_group_data(json): def filter_firewall_schedule_group_data(json):
@ -208,48 +225,66 @@ def filter_firewall_schedule_group_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_schedule_group(data, fos): def firewall_schedule_group(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_schedule_group_data = data['firewall_schedule_group'] firewall_schedule_group_data = data['firewall_schedule_group']
filtered_data = filter_firewall_schedule_group_data(firewall_schedule_group_data) filtered_data = underscore_to_hyphen(filter_firewall_schedule_group_data(firewall_schedule_group_data))
if firewall_schedule_group_data['state'] == "present":
if state == "present":
return fos.set('firewall.schedule', return fos.set('firewall.schedule',
'group', 'group',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_schedule_group_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.schedule', return fos.delete('firewall.schedule',
'group', 'group',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_schedule(data, fos): def fortios_firewall_schedule(data, fos):
login(data)
methodlist = ['firewall_schedule_group'] if data['firewall_schedule_group']:
for method in methodlist: resp = firewall_schedule_group(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_schedule_group": { "firewall_schedule_group": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"member": {"required": False, "type": "list", "member": {"required": False, "type": "list",
"options": { "options": {
@ -263,15 +298,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_schedule_onetime module: fortios_firewall_schedule_onetime
short_description: Onetime schedule configuration in Fortinet's FortiOS and FortiGate. short_description: Onetime schedule configuration in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_schedule feature and onetime category. user to set and modify firewall_schedule feature and onetime category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,56 +41,74 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_schedule_onetime: firewall_schedule_onetime:
description: description:
- Onetime schedule configuration. - Onetime schedule configuration.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
color: color:
description: description:
- Color of icon on the GUI. - Color of icon on the GUI.
type: int
end: end:
description: description:
- "Schedule end date and time, format hh:mm yyyy/mm/dd." - "Schedule end date and time, format hh:mm yyyy/mm/dd."
expiration-days: type: str
expiration_days:
description: description:
- Write an event log message this many days before the schedule expires. - Write an event log message this many days before the schedule expires.
type: int
name: name:
description: description:
- Onetime schedule name. - Onetime schedule name.
required: true required: true
type: str
start: start:
description: description:
- "Schedule start date and time, format hh:mm yyyy/mm/dd." - "Schedule start date and time, format hh:mm yyyy/mm/dd."
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -103,6 +118,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Onetime schedule configuration. - name: Onetime schedule configuration.
fortios_firewall_schedule_onetime: fortios_firewall_schedule_onetime:
@ -111,11 +127,11 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_schedule_onetime: firewall_schedule_onetime:
state: "present"
color: "3" color: "3"
end: "<your_own_value>" end: "<your_own_value>"
expiration-days: "5" expiration_days: "5"
name: "default_name_6" name: "default_name_6"
start: "<your_own_value>" start: "<your_own_value>"
''' '''
@ -180,14 +196,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -195,11 +213,11 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_schedule_onetime_data(json): def filter_firewall_schedule_onetime_data(json):
option_list = ['color', 'end', 'expiration-days', option_list = ['color', 'end', 'expiration_days',
'name', 'start'] 'name', 'start']
dictionary = {} dictionary = {}
@ -210,51 +228,69 @@ def filter_firewall_schedule_onetime_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_schedule_onetime(data, fos): def firewall_schedule_onetime(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_schedule_onetime_data = data['firewall_schedule_onetime'] firewall_schedule_onetime_data = data['firewall_schedule_onetime']
filtered_data = filter_firewall_schedule_onetime_data(firewall_schedule_onetime_data) filtered_data = underscore_to_hyphen(filter_firewall_schedule_onetime_data(firewall_schedule_onetime_data))
if firewall_schedule_onetime_data['state'] == "present":
if state == "present":
return fos.set('firewall.schedule', return fos.set('firewall.schedule',
'onetime', 'onetime',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_schedule_onetime_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.schedule', return fos.delete('firewall.schedule',
'onetime', 'onetime',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_schedule(data, fos): def fortios_firewall_schedule(data, fos):
login(data)
methodlist = ['firewall_schedule_onetime'] if data['firewall_schedule_onetime']:
for method in methodlist: resp = firewall_schedule_onetime(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_schedule_onetime": { "firewall_schedule_onetime": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"end": {"required": False, "type": "str"}, "end": {"required": False, "type": "str"},
"expiration-days": {"required": False, "type": "int"}, "expiration_days": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"start": {"required": False, "type": "str"} "start": {"required": False, "type": "str"}
@ -264,15 +300,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_schedule_recurring module: fortios_firewall_schedule_recurring
short_description: Recurring schedule configuration in Fortinet's FortiOS and FortiGate. short_description: Recurring schedule configuration in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_schedule feature and recurring category. user to set and modify firewall_schedule feature and recurring category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,46 +41,61 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_schedule_recurring: firewall_schedule_recurring:
description: description:
- Recurring schedule configuration. - Recurring schedule configuration.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
color: color:
description: description:
- Color of icon on the GUI. - Color of icon on the GUI.
type: int
day: day:
description: description:
- One or more days of the week on which the schedule is valid. Separate the names of the days with a space. - One or more days of the week on which the schedule is valid. Separate the names of the days with a space.
type: str
choices: choices:
- sunday - sunday
- monday - monday
@ -96,13 +108,16 @@ options:
end: end:
description: description:
- "Time of day to end the schedule, format hh:mm." - "Time of day to end the schedule, format hh:mm."
type: str
name: name:
description: description:
- Recurring schedule name. - Recurring schedule name.
required: true required: true
type: str
start: start:
description: description:
- "Time of day to start the schedule, format hh:mm." - "Time of day to start the schedule, format hh:mm."
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -112,6 +127,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Recurring schedule configuration. - name: Recurring schedule configuration.
fortios_firewall_schedule_recurring: fortios_firewall_schedule_recurring:
@ -120,8 +136,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_schedule_recurring: firewall_schedule_recurring:
state: "present"
color: "3" color: "3"
day: "sunday" day: "sunday"
end: "<your_own_value>" end: "<your_own_value>"
@ -189,14 +205,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -204,7 +222,7 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_schedule_recurring_data(json): def filter_firewall_schedule_recurring_data(json):
@ -219,48 +237,66 @@ def filter_firewall_schedule_recurring_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_schedule_recurring(data, fos): def firewall_schedule_recurring(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_schedule_recurring_data = data['firewall_schedule_recurring'] firewall_schedule_recurring_data = data['firewall_schedule_recurring']
filtered_data = filter_firewall_schedule_recurring_data(firewall_schedule_recurring_data) filtered_data = underscore_to_hyphen(filter_firewall_schedule_recurring_data(firewall_schedule_recurring_data))
if firewall_schedule_recurring_data['state'] == "present":
if state == "present":
return fos.set('firewall.schedule', return fos.set('firewall.schedule',
'recurring', 'recurring',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_schedule_recurring_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.schedule', return fos.delete('firewall.schedule',
'recurring', 'recurring',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_schedule(data, fos): def fortios_firewall_schedule(data, fos):
login(data)
methodlist = ['firewall_schedule_recurring'] if data['firewall_schedule_recurring']:
for method in methodlist: resp = firewall_schedule_recurring(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_schedule_recurring": { "firewall_schedule_recurring": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"day": {"required": False, "type": "str", "day": {"required": False, "type": "str",
"choices": ["sunday", "monday", "tuesday", "choices": ["sunday", "monday", "tuesday",
@ -276,15 +312,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_schedule(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_service_category module: fortios_firewall_service_category
short_description: Configure service categories in Fortinet's FortiOS and FortiGate. short_description: Configure service categories in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_service feature and category category. user to set and modify firewall_service feature and category category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,47 +41,62 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_service_category: firewall_service_category:
description: description:
- Configure service categories. - Configure service categories.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
comment: comment:
description: description:
- Comment. - Comment.
type: str
name: name:
description: description:
- Service category name. - Service category name.
required: true required: true
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -94,6 +106,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure service categories. - name: Configure service categories.
fortios_firewall_service_category: fortios_firewall_service_category:
@ -102,8 +115,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_service_category: firewall_service_category:
state: "present"
comment: "Comment." comment: "Comment."
name: "default_name_4" name: "default_name_4"
''' '''
@ -168,14 +181,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -183,7 +198,7 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_service_category_data(json): def filter_firewall_service_category_data(json):
@ -197,48 +212,66 @@ def filter_firewall_service_category_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_service_category(data, fos): def firewall_service_category(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_service_category_data = data['firewall_service_category'] firewall_service_category_data = data['firewall_service_category']
filtered_data = filter_firewall_service_category_data(firewall_service_category_data) filtered_data = underscore_to_hyphen(filter_firewall_service_category_data(firewall_service_category_data))
if firewall_service_category_data['state'] == "present":
if state == "present":
return fos.set('firewall.service', return fos.set('firewall.service',
'category', 'category',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_service_category_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.service', return fos.delete('firewall.service',
'category', 'category',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_service(data, fos): def fortios_firewall_service(data, fos):
login(data)
methodlist = ['firewall_service_category'] if data['firewall_service_category']:
for method in methodlist: resp = firewall_service_category(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_service_category": { "firewall_service_category": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
@ -248,15 +281,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_service(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_service_custom module: fortios_firewall_service_custom
short_description: Configure custom services in Fortinet's FortiOS and FortiGate. short_description: Configure custom services in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_service feature and custom category. user to set and modify firewall_service feature and custom category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,51 +41,67 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_service_custom: firewall_service_custom:
description: description:
- Configure custom services. - Configure custom services.
default: null default: null
type: dict
suboptions: suboptions:
state: app_category:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
app-category:
description: description:
- Application category ID. - Application category ID.
type: list
suboptions: suboptions:
id: id:
description: description:
- Application category id. - Application category id.
required: true required: true
app-service-type: type: int
app_service_type:
description: description:
- Application service type. - Application service type.
type: str
choices: choices:
- disable - disable
- app-id - app-id
@ -96,17 +109,21 @@ options:
application: application:
description: description:
- Application ID. - Application ID.
type: list
suboptions: suboptions:
id: id:
description: description:
- Application id. - Application id.
required: true required: true
type: int
category: category:
description: description:
- Service category. Source firewall.service.category.name. - Service category. Source firewall.service.category.name.
check-reset-range: type: str
check_reset_range:
description: description:
- Configure the type of ICMP error message verification. - Configure the type of ICMP error message verification.
type: str
choices: choices:
- disable - disable
- strict - strict
@ -114,15 +131,19 @@ options:
color: color:
description: description:
- Color of icon on the GUI. - Color of icon on the GUI.
type: int
comment: comment:
description: description:
- Comment. - Comment.
type: str
fqdn: fqdn:
description: description:
- Fully qualified domain name. - Fully qualified domain name.
type: str
helper: helper:
description: description:
- Helper name. - Helper name.
type: str
choices: choices:
- auto - auto
- disable - disable
@ -147,19 +168,24 @@ options:
icmpcode: icmpcode:
description: description:
- ICMP code. - ICMP code.
type: int
icmptype: icmptype:
description: description:
- ICMP type. - ICMP type.
type: int
iprange: iprange:
description: description:
- Start and end of the IP range associated with service. - Start and end of the IP range associated with service.
type: str
name: name:
description: description:
- Custom service name. - Custom service name.
required: true required: true
type: str
protocol: protocol:
description: description:
- Protocol type based on IANA numbers. - Protocol type based on IANA numbers.
type: str
choices: choices:
- TCP/UDP/SCTP - TCP/UDP/SCTP
- ICMP - ICMP
@ -171,42 +197,53 @@ options:
- SOCKS-TCP - SOCKS-TCP
- SOCKS-UDP - SOCKS-UDP
- ALL - ALL
protocol-number: protocol_number:
description: description:
- IP protocol number. - IP protocol number.
type: int
proxy: proxy:
description: description:
- Enable/disable web proxy service. - Enable/disable web proxy service.
type: str
choices: choices:
- enable - enable
- disable - disable
sctp-portrange: sctp_portrange:
description: description:
- Multiple SCTP port ranges. - Multiple SCTP port ranges.
session-ttl: type: str
session_ttl:
description: description:
- Session TTL (300 - 604800, 0 = default). - Session TTL (300 - 604800, 0 = default).
tcp-halfclose-timer: type: int
tcp_halfclose_timer:
description: description:
- Wait time to close a TCP session waiting for an unanswered FIN packet (1 - 86400 sec, 0 = default). - Wait time to close a TCP session waiting for an unanswered FIN packet (1 - 86400 sec, 0 = default).
tcp-halfopen-timer: type: int
tcp_halfopen_timer:
description: description:
- Wait time to close a TCP session waiting for an unanswered open session packet (1 - 86400 sec, 0 = default). - Wait time to close a TCP session waiting for an unanswered open session packet (1 - 86400 sec, 0 = default).
tcp-portrange: type: int
tcp_portrange:
description: description:
- Multiple TCP port ranges. - Multiple TCP port ranges.
tcp-timewait-timer: type: str
tcp_timewait_timer:
description: description:
- Set the length of the TCP TIME-WAIT state in seconds (1 - 300 sec, 0 = default). - Set the length of the TCP TIME-WAIT state in seconds (1 - 300 sec, 0 = default).
udp-idle-timer: type: int
udp_idle_timer:
description: description:
- UDP half close timeout (0 - 86400 sec, 0 = default). - UDP half close timeout (0 - 86400 sec, 0 = default).
udp-portrange: type: int
udp_portrange:
description: description:
- Multiple UDP port ranges. - Multiple UDP port ranges.
type: str
visibility: visibility:
description: description:
- Enable/disable the visibility of the service on the GUI. - Enable/disable the visibility of the service on the GUI.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -219,6 +256,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure custom services. - name: Configure custom services.
fortios_firewall_service_custom: fortios_firewall_service_custom:
@ -227,17 +265,17 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_service_custom: firewall_service_custom:
state: "present" app_category:
app-category:
- -
id: "4" id: "4"
app-service-type: "disable" app_service_type: "disable"
application: application:
- -
id: "7" id: "7"
category: "<your_own_value> (source firewall.service.category.name)" category: "<your_own_value> (source firewall.service.category.name)"
check-reset-range: "disable" check_reset_range: "disable"
color: "10" color: "10"
comment: "Comment." comment: "Comment."
fqdn: "<your_own_value>" fqdn: "<your_own_value>"
@ -247,16 +285,16 @@ EXAMPLES = '''
iprange: "<your_own_value>" iprange: "<your_own_value>"
name: "default_name_17" name: "default_name_17"
protocol: "TCP/UDP/SCTP" protocol: "TCP/UDP/SCTP"
protocol-number: "19" protocol_number: "19"
proxy: "enable" proxy: "enable"
sctp-portrange: "<your_own_value>" sctp_portrange: "<your_own_value>"
session-ttl: "22" session_ttl: "22"
tcp-halfclose-timer: "23" tcp_halfclose_timer: "23"
tcp-halfopen-timer: "24" tcp_halfopen_timer: "24"
tcp-portrange: "<your_own_value>" tcp_portrange: "<your_own_value>"
tcp-timewait-timer: "26" tcp_timewait_timer: "26"
udp-idle-timer: "27" udp_idle_timer: "27"
udp-portrange: "<your_own_value>" udp_portrange: "<your_own_value>"
visibility: "enable" visibility: "enable"
''' '''
@ -320,14 +358,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -335,18 +375,18 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_service_custom_data(json): def filter_firewall_service_custom_data(json):
option_list = ['app-category', 'app-service-type', 'application', option_list = ['app_category', 'app_service_type', 'application',
'category', 'check-reset-range', 'color', 'category', 'check_reset_range', 'color',
'comment', 'fqdn', 'helper', 'comment', 'fqdn', 'helper',
'icmpcode', 'icmptype', 'iprange', 'icmpcode', 'icmptype', 'iprange',
'name', 'protocol', 'protocol-number', 'name', 'protocol', 'protocol_number',
'proxy', 'sctp-portrange', 'session-ttl', 'proxy', 'sctp_portrange', 'session_ttl',
'tcp-halfclose-timer', 'tcp-halfopen-timer', 'tcp-portrange', 'tcp_halfclose_timer', 'tcp_halfopen_timer', 'tcp_portrange',
'tcp-timewait-timer', 'udp-idle-timer', 'udp-portrange', 'tcp_timewait_timer', 'udp_idle_timer', 'udp_portrange',
'visibility'] 'visibility']
dictionary = {} dictionary = {}
@ -357,60 +397,78 @@ def filter_firewall_service_custom_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_service_custom(data, fos): def firewall_service_custom(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_service_custom_data = data['firewall_service_custom'] firewall_service_custom_data = data['firewall_service_custom']
filtered_data = filter_firewall_service_custom_data(firewall_service_custom_data) filtered_data = underscore_to_hyphen(filter_firewall_service_custom_data(firewall_service_custom_data))
if firewall_service_custom_data['state'] == "present":
if state == "present":
return fos.set('firewall.service', return fos.set('firewall.service',
'custom', 'custom',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_service_custom_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.service', return fos.delete('firewall.service',
'custom', 'custom',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_service(data, fos): def fortios_firewall_service(data, fos):
login(data)
methodlist = ['firewall_service_custom'] if data['firewall_service_custom']:
for method in methodlist: resp = firewall_service_custom(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_service_custom": { "firewall_service_custom": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "app_category": {"required": False, "type": "list",
"choices": ["present", "absent"]},
"app-category": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"app-service-type": {"required": False, "type": "str", "app_service_type": {"required": False, "type": "str",
"choices": ["disable", "app-id", "app-category"]}, "choices": ["disable", "app-id", "app-category"]},
"application": {"required": False, "type": "list", "application": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"category": {"required": False, "type": "str"}, "category": {"required": False, "type": "str"},
"check-reset-range": {"required": False, "type": "str", "check_reset_range": {"required": False, "type": "str",
"choices": ["disable", "strict", "default"]}, "choices": ["disable", "strict", "default"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
@ -432,17 +490,17 @@ def main():
"IP", "HTTP", "FTP", "IP", "HTTP", "FTP",
"CONNECT", "SOCKS-TCP", "SOCKS-UDP", "CONNECT", "SOCKS-TCP", "SOCKS-UDP",
"ALL"]}, "ALL"]},
"protocol-number": {"required": False, "type": "int"}, "protocol_number": {"required": False, "type": "int"},
"proxy": {"required": False, "type": "str", "proxy": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"sctp-portrange": {"required": False, "type": "str"}, "sctp_portrange": {"required": False, "type": "str"},
"session-ttl": {"required": False, "type": "int"}, "session_ttl": {"required": False, "type": "int"},
"tcp-halfclose-timer": {"required": False, "type": "int"}, "tcp_halfclose_timer": {"required": False, "type": "int"},
"tcp-halfopen-timer": {"required": False, "type": "int"}, "tcp_halfopen_timer": {"required": False, "type": "int"},
"tcp-portrange": {"required": False, "type": "str"}, "tcp_portrange": {"required": False, "type": "str"},
"tcp-timewait-timer": {"required": False, "type": "int"}, "tcp_timewait_timer": {"required": False, "type": "int"},
"udp-idle-timer": {"required": False, "type": "int"}, "udp_idle_timer": {"required": False, "type": "int"},
"udp-portrange": {"required": False, "type": "str"}, "udp_portrange": {"required": False, "type": "str"},
"visibility": {"required": False, "type": "str", "visibility": {"required": False, "type": "str",
"choices": ["enable", "disable"]} "choices": ["enable", "disable"]}
@ -452,15 +510,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_service(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_service_group module: fortios_firewall_service_group
short_description: Configure service groups in Fortinet's FortiOS and FortiGate. short_description: Configure service groups in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_service feature and group category. user to set and modify firewall_service feature and group category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,61 +41,80 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_service_group: firewall_service_group:
description: description:
- Configure service groups. - Configure service groups.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
color: color:
description: description:
- Color of icon on the GUI. - Color of icon on the GUI.
type: int
comment: comment:
description: description:
- Comment. - Comment.
type: str
member: member:
description: description:
- Service objects contained within the group. - Service objects contained within the group.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.service.custom.name firewall.service.group.name. - Address name. Source firewall.service.custom.name firewall.service.group.name.
required: true required: true
type: str
name: name:
description: description:
- Address group name. - Address group name.
required: true required: true
type: str
proxy: proxy:
description: description:
- Enable/disable web proxy service group. - Enable/disable web proxy service group.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -111,6 +127,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure service groups. - name: Configure service groups.
fortios_firewall_service_group: fortios_firewall_service_group:
@ -119,8 +136,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_service_group: firewall_service_group:
state: "present"
color: "3" color: "3"
comment: "Comment." comment: "Comment."
member: member:
@ -190,14 +207,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -205,7 +224,7 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_service_group_data(json): def filter_firewall_service_group_data(json):
@ -220,48 +239,66 @@ def filter_firewall_service_group_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_service_group(data, fos): def firewall_service_group(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_service_group_data = data['firewall_service_group'] firewall_service_group_data = data['firewall_service_group']
filtered_data = filter_firewall_service_group_data(firewall_service_group_data) filtered_data = underscore_to_hyphen(filter_firewall_service_group_data(firewall_service_group_data))
if firewall_service_group_data['state'] == "present":
if state == "present":
return fos.set('firewall.service', return fos.set('firewall.service',
'group', 'group',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_service_group_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.service', return fos.delete('firewall.service',
'group', 'group',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_service(data, fos): def fortios_firewall_service(data, fos):
login(data)
methodlist = ['firewall_service_group'] if data['firewall_service_group']:
for method in methodlist: resp = firewall_service_group(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_service_group": { "firewall_service_group": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"member": {"required": False, "type": "list", "member": {"required": False, "type": "list",
@ -278,15 +315,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_service(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_service(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_shaper_per_ip_shaper module: fortios_firewall_shaper_per_ip_shaper
short_description: Configure per-IP traffic shaper in Fortinet's FortiOS and FortiGate. short_description: Configure per-IP traffic shaper in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_shaper feature and per_ip_shaper category. user to set and modify firewall_shaper feature and per_ip_shaper category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,75 +41,96 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_shaper_per_ip_shaper: firewall_shaper_per_ip_shaper:
description: description:
- Configure per-IP traffic shaper. - Configure per-IP traffic shaper.
default: null default: null
type: dict
suboptions: suboptions:
state: bandwidth_unit:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
bandwidth-unit:
description: description:
- Unit of measurement for maximum bandwidth for this shaper (Kbps, Mbps or Gbps). - Unit of measurement for maximum bandwidth for this shaper (Kbps, Mbps or Gbps).
type: str
choices: choices:
- kbps - kbps
- mbps - mbps
- gbps - gbps
diffserv-forward: diffserv_forward:
description: description:
- Enable/disable changing the Forward (original) DiffServ setting applied to traffic accepted by this shaper. - Enable/disable changing the Forward (original) DiffServ setting applied to traffic accepted by this shaper.
type: str
choices: choices:
- enable - enable
- disable - disable
diffserv-reverse: diffserv_reverse:
description: description:
- Enable/disable changing the Reverse (reply) DiffServ setting applied to traffic accepted by this shaper. - Enable/disable changing the Reverse (reply) DiffServ setting applied to traffic accepted by this shaper.
type: str
choices: choices:
- enable - enable
- disable - disable
diffservcode-forward: diffservcode_forward:
description: description:
- Forward (original) DiffServ setting to be applied to traffic accepted by this shaper. - Forward (original) DiffServ setting to be applied to traffic accepted by this shaper.
diffservcode-rev: type: str
diffservcode_rev:
description: description:
- Reverse (reply) DiffServ setting to be applied to traffic accepted by this shaper. - Reverse (reply) DiffServ setting to be applied to traffic accepted by this shaper.
max-bandwidth: type: str
max_bandwidth:
description: description:
- Upper bandwidth limit enforced by this shaper (0 - 16776000). 0 means no limit. Units depend on the bandwidth-unit setting. - Upper bandwidth limit enforced by this shaper (0 - 16776000). 0 means no limit. Units depend on the bandwidth-unit setting.
max-concurrent-session: type: int
max_concurrent_session:
description: description:
- Maximum number of concurrent sessions allowed by this shaper (0 - 2097000). 0 means no limit. - Maximum number of concurrent sessions allowed by this shaper (0 - 2097000). 0 means no limit.
type: int
name: name:
description: description:
- Traffic shaper name. - Traffic shaper name.
required: true required: true
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -122,6 +140,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure per-IP traffic shaper. - name: Configure per-IP traffic shaper.
fortios_firewall_shaper_per_ip_shaper: fortios_firewall_shaper_per_ip_shaper:
@ -130,15 +149,15 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_shaper_per_ip_shaper: firewall_shaper_per_ip_shaper:
state: "present" bandwidth_unit: "kbps"
bandwidth-unit: "kbps" diffserv_forward: "enable"
diffserv-forward: "enable" diffserv_reverse: "enable"
diffserv-reverse: "enable" diffservcode_forward: "<your_own_value>"
diffservcode-forward: "<your_own_value>" diffservcode_rev: "<your_own_value>"
diffservcode-rev: "<your_own_value>" max_bandwidth: "8"
max-bandwidth: "8" max_concurrent_session: "9"
max-concurrent-session: "9"
name: "default_name_10" name: "default_name_10"
''' '''
@ -202,14 +221,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -217,13 +238,13 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_shaper_per_ip_shaper_data(json): def filter_firewall_shaper_per_ip_shaper_data(json):
option_list = ['bandwidth-unit', 'diffserv-forward', 'diffserv-reverse', option_list = ['bandwidth_unit', 'diffserv_forward', 'diffserv_reverse',
'diffservcode-forward', 'diffservcode-rev', 'max-bandwidth', 'diffservcode_forward', 'diffservcode_rev', 'max_bandwidth',
'max-concurrent-session', 'name'] 'max_concurrent_session', 'name']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -233,58 +254,76 @@ def filter_firewall_shaper_per_ip_shaper_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_shaper_per_ip_shaper(data, fos): def firewall_shaper_per_ip_shaper(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_shaper_per_ip_shaper_data = data['firewall_shaper_per_ip_shaper'] firewall_shaper_per_ip_shaper_data = data['firewall_shaper_per_ip_shaper']
filtered_data = filter_firewall_shaper_per_ip_shaper_data(firewall_shaper_per_ip_shaper_data) filtered_data = underscore_to_hyphen(filter_firewall_shaper_per_ip_shaper_data(firewall_shaper_per_ip_shaper_data))
if firewall_shaper_per_ip_shaper_data['state'] == "present":
if state == "present":
return fos.set('firewall.shaper', return fos.set('firewall.shaper',
'per-ip-shaper', 'per-ip-shaper',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_shaper_per_ip_shaper_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.shaper', return fos.delete('firewall.shaper',
'per-ip-shaper', 'per-ip-shaper',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_shaper(data, fos): def fortios_firewall_shaper(data, fos):
login(data)
methodlist = ['firewall_shaper_per_ip_shaper'] if data['firewall_shaper_per_ip_shaper']:
for method in methodlist: resp = firewall_shaper_per_ip_shaper(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_shaper_per_ip_shaper": { "firewall_shaper_per_ip_shaper": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "bandwidth_unit": {"required": False, "type": "str",
"choices": ["present", "absent"]},
"bandwidth-unit": {"required": False, "type": "str",
"choices": ["kbps", "mbps", "gbps"]}, "choices": ["kbps", "mbps", "gbps"]},
"diffserv-forward": {"required": False, "type": "str", "diffserv_forward": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"diffserv-reverse": {"required": False, "type": "str", "diffserv_reverse": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"diffservcode-forward": {"required": False, "type": "str"}, "diffservcode_forward": {"required": False, "type": "str"},
"diffservcode-rev": {"required": False, "type": "str"}, "diffservcode_rev": {"required": False, "type": "str"},
"max-bandwidth": {"required": False, "type": "int"}, "max_bandwidth": {"required": False, "type": "int"},
"max-concurrent-session": {"required": False, "type": "int"}, "max_concurrent_session": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
} }
@ -293,15 +332,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_shaper_traffic_shaper module: fortios_firewall_shaper_traffic_shaper
short_description: Configure shared traffic shaper in Fortinet's FortiOS and FortiGate. short_description: Configure shared traffic shaper in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_shaper feature and traffic_shaper category. user to set and modify firewall_shaper feature and traffic_shaper category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,43 +41,57 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_shaper_traffic_shaper: firewall_shaper_traffic_shaper:
description: description:
- Configure shared traffic shaper. - Configure shared traffic shaper.
default: null default: null
type: dict
suboptions: suboptions:
state: bandwidth_unit:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
bandwidth-unit:
description: description:
- Unit of measurement for guaranteed and maximum bandwidth for this shaper (Kbps, Mbps or Gbps). - Unit of measurement for guaranteed and maximum bandwidth for this shaper (Kbps, Mbps or Gbps).
type: str
choices: choices:
- kbps - kbps
- mbps - mbps
@ -88,32 +99,39 @@ options:
diffserv: diffserv:
description: description:
- Enable/disable changing the DiffServ setting applied to traffic accepted by this shaper. - Enable/disable changing the DiffServ setting applied to traffic accepted by this shaper.
type: str
choices: choices:
- enable - enable
- disable - disable
diffservcode: diffservcode:
description: description:
- DiffServ setting to be applied to traffic accepted by this shaper. - DiffServ setting to be applied to traffic accepted by this shaper.
guaranteed-bandwidth: type: str
guaranteed_bandwidth:
description: description:
- Amount of bandwidth guaranteed for this shaper (0 - 16776000). Units depend on the bandwidth-unit setting. - Amount of bandwidth guaranteed for this shaper (0 - 16776000). Units depend on the bandwidth-unit setting.
maximum-bandwidth: type: int
maximum_bandwidth:
description: description:
- Upper bandwidth limit enforced by this shaper (0 - 16776000). 0 means no limit. Units depend on the bandwidth-unit setting. - Upper bandwidth limit enforced by this shaper (0 - 16776000). 0 means no limit. Units depend on the bandwidth-unit setting.
type: int
name: name:
description: description:
- Traffic shaper name. - Traffic shaper name.
required: true required: true
per-policy: type: str
per_policy:
description: description:
- Enable/disable applying a separate shaper for each policy. For example, if enabled the guaranteed bandwidth is applied separately for - Enable/disable applying a separate shaper for each policy. For example, if enabled the guaranteed bandwidth is applied separately for
each policy. each policy.
type: str
choices: choices:
- disable - disable
- enable - enable
priority: priority:
description: description:
- Higher priority traffic is more likely to be forwarded without delays and without compromising the guaranteed bandwidth. - Higher priority traffic is more likely to be forwarded without delays and without compromising the guaranteed bandwidth.
type: str
choices: choices:
- low - low
- medium - medium
@ -127,6 +145,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure shared traffic shaper. - name: Configure shared traffic shaper.
fortios_firewall_shaper_traffic_shaper: fortios_firewall_shaper_traffic_shaper:
@ -135,15 +154,15 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_shaper_traffic_shaper: firewall_shaper_traffic_shaper:
state: "present" bandwidth_unit: "kbps"
bandwidth-unit: "kbps"
diffserv: "enable" diffserv: "enable"
diffservcode: "<your_own_value>" diffservcode: "<your_own_value>"
guaranteed-bandwidth: "6" guaranteed_bandwidth: "6"
maximum-bandwidth: "7" maximum_bandwidth: "7"
name: "default_name_8" name: "default_name_8"
per-policy: "disable" per_policy: "disable"
priority: "low" priority: "low"
''' '''
@ -207,14 +226,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -222,13 +243,13 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_shaper_traffic_shaper_data(json): def filter_firewall_shaper_traffic_shaper_data(json):
option_list = ['bandwidth-unit', 'diffserv', 'diffservcode', option_list = ['bandwidth_unit', 'diffserv', 'diffservcode',
'guaranteed-bandwidth', 'maximum-bandwidth', 'name', 'guaranteed_bandwidth', 'maximum_bandwidth', 'name',
'per-policy', 'priority'] 'per_policy', 'priority']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -238,57 +259,75 @@ def filter_firewall_shaper_traffic_shaper_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_shaper_traffic_shaper(data, fos): def firewall_shaper_traffic_shaper(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_shaper_traffic_shaper_data = data['firewall_shaper_traffic_shaper'] firewall_shaper_traffic_shaper_data = data['firewall_shaper_traffic_shaper']
filtered_data = filter_firewall_shaper_traffic_shaper_data(firewall_shaper_traffic_shaper_data) filtered_data = underscore_to_hyphen(filter_firewall_shaper_traffic_shaper_data(firewall_shaper_traffic_shaper_data))
if firewall_shaper_traffic_shaper_data['state'] == "present":
if state == "present":
return fos.set('firewall.shaper', return fos.set('firewall.shaper',
'traffic-shaper', 'traffic-shaper',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_shaper_traffic_shaper_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.shaper', return fos.delete('firewall.shaper',
'traffic-shaper', 'traffic-shaper',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_shaper(data, fos): def fortios_firewall_shaper(data, fos):
login(data)
methodlist = ['firewall_shaper_traffic_shaper'] if data['firewall_shaper_traffic_shaper']:
for method in methodlist: resp = firewall_shaper_traffic_shaper(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_shaper_traffic_shaper": { "firewall_shaper_traffic_shaper": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "bandwidth_unit": {"required": False, "type": "str",
"choices": ["present", "absent"]},
"bandwidth-unit": {"required": False, "type": "str",
"choices": ["kbps", "mbps", "gbps"]}, "choices": ["kbps", "mbps", "gbps"]},
"diffserv": {"required": False, "type": "str", "diffserv": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"diffservcode": {"required": False, "type": "str"}, "diffservcode": {"required": False, "type": "str"},
"guaranteed-bandwidth": {"required": False, "type": "int"}, "guaranteed_bandwidth": {"required": False, "type": "int"},
"maximum-bandwidth": {"required": False, "type": "int"}, "maximum_bandwidth": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"per-policy": {"required": False, "type": "str", "per_policy": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"priority": {"required": False, "type": "str", "priority": {"required": False, "type": "str",
"choices": ["low", "medium", "high"]} "choices": ["low", "medium", "high"]}
@ -299,15 +338,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_shaper(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_shaping_policy module: fortios_firewall_shaping_policy
short_description: Configure shaping policies in Fortinet's FortiOS and FortiGate. short_description: Configure shaping policies in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and shaping_policy category. user to set and modify firewall feature and shaping_policy category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,206 +41,260 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_shaping_policy: firewall_shaping_policy:
description: description:
- Configure shaping policies. - Configure shaping policies.
default: null default: null
type: dict
suboptions: suboptions:
state: app_category:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
app-category:
description: description:
- IDs of one or more application categories that this shaper applies application control traffic shaping to. - IDs of one or more application categories that this shaper applies application control traffic shaping to.
type: list
suboptions: suboptions:
id: id:
description: description:
- Category IDs. - Category IDs.
required: true required: true
type: int
application: application:
description: description:
- IDs of one or more applications that this shaper applies application control traffic shaping to. - IDs of one or more applications that this shaper applies application control traffic shaping to.
type: list
suboptions: suboptions:
id: id:
description: description:
- Application IDs. - Application IDs.
required: true required: true
class-id: type: int
class_id:
description: description:
- Traffic class ID. - Traffic class ID.
type: int
comment: comment:
description: description:
- Comments. - Comments.
type: str
dstaddr: dstaddr:
description: description:
- IPv4 destination address and address group names. - IPv4 destination address and address group names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address.name firewall.addrgrp.name. - Address name. Source firewall.address.name firewall.addrgrp.name.
required: true required: true
type: str
dstaddr6: dstaddr6:
description: description:
- IPv6 destination address and address group names. - IPv6 destination address and address group names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address6.name firewall.addrgrp6.name. - Address name. Source firewall.address6.name firewall.addrgrp6.name.
required: true required: true
type: str
dstintf: dstintf:
description: description:
- One or more outgoing (egress) interfaces. - One or more outgoing (egress) interfaces.
type: list
suboptions: suboptions:
name: name:
description: description:
- Interface name. Source system.interface.name system.zone.name. - Interface name. Source system.interface.name system.zone.name.
required: true required: true
type: str
groups: groups:
description: description:
- Apply this traffic shaping policy to user groups that have authenticated with the FortiGate. - Apply this traffic shaping policy to user groups that have authenticated with the FortiGate.
type: list
suboptions: suboptions:
name: name:
description: description:
- Group name. Source user.group.name. - Group name. Source user.group.name.
required: true required: true
type: str
id: id:
description: description:
- Shaping policy ID. - Shaping policy ID.
required: true required: true
internet-service: type: int
internet_service:
description: description:
- Enable/disable use of Internet Services for this policy. If enabled, destination address and service are not used. - Enable/disable use of Internet Services for this policy. If enabled, destination address and service are not used.
type: str
choices: choices:
- enable - enable
- disable - disable
internet-service-custom: internet_service_custom:
description: description:
- Custom Internet Service name. - Custom Internet Service name.
type: list
suboptions: suboptions:
name: name:
description: description:
- Custom Internet Service name. Source firewall.internet-service-custom.name. - Custom Internet Service name. Source firewall.internet-service-custom.name.
required: true required: true
internet-service-id: type: str
internet_service_id:
description: description:
- Internet Service ID. - Internet Service ID.
type: list
suboptions: suboptions:
id: id:
description: description:
- Internet Service ID. Source firewall.internet-service.id. - Internet Service ID. Source firewall.internet-service.id.
required: true required: true
internet-service-src: type: int
internet_service_src:
description: description:
- Enable/disable use of Internet Services in source for this policy. If enabled, source address is not used. - Enable/disable use of Internet Services in source for this policy. If enabled, source address is not used.
type: str
choices: choices:
- enable - enable
- disable - disable
internet-service-src-custom: internet_service_src_custom:
description: description:
- Custom Internet Service source name. - Custom Internet Service source name.
type: list
suboptions: suboptions:
name: name:
description: description:
- Custom Internet Service name. Source firewall.internet-service-custom.name. - Custom Internet Service name. Source firewall.internet-service-custom.name.
required: true required: true
internet-service-src-id: type: str
internet_service_src_id:
description: description:
- Internet Service source ID. - Internet Service source ID.
type: list
suboptions: suboptions:
id: id:
description: description:
- Internet Service ID. Source firewall.internet-service.id. - Internet Service ID. Source firewall.internet-service.id.
required: true required: true
ip-version: type: int
ip_version:
description: description:
- Apply this traffic shaping policy to IPv4 or IPv6 traffic. - Apply this traffic shaping policy to IPv4 or IPv6 traffic.
type: str
choices: choices:
- 4 - 4
- 6 - 6
per-ip-shaper: per_ip_shaper:
description: description:
- Per-IP traffic shaper to apply with this policy. Source firewall.shaper.per-ip-shaper.name. - Per-IP traffic shaper to apply with this policy. Source firewall.shaper.per-ip-shaper.name.
type: str
schedule: schedule:
description: description:
- Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name. - Schedule name. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name.
type: str
service: service:
description: description:
- Service and service group names. - Service and service group names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Service name. Source firewall.service.custom.name firewall.service.group.name. - Service name. Source firewall.service.custom.name firewall.service.group.name.
required: true required: true
type: str
srcaddr: srcaddr:
description: description:
- IPv4 source address and address group names. - IPv4 source address and address group names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address.name firewall.addrgrp.name. - Address name. Source firewall.address.name firewall.addrgrp.name.
required: true required: true
type: str
srcaddr6: srcaddr6:
description: description:
- IPv6 source address and address group names. - IPv6 source address and address group names.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.address6.name firewall.addrgrp6.name. - Address name. Source firewall.address6.name firewall.addrgrp6.name.
required: true required: true
type: str
status: status:
description: description:
- Enable/disable this traffic shaping policy. - Enable/disable this traffic shaping policy.
type: str
choices: choices:
- enable - enable
- disable - disable
traffic-shaper: traffic_shaper:
description: description:
- Traffic shaper to apply to traffic forwarded by the firewall policy. Source firewall.shaper.traffic-shaper.name. - Traffic shaper to apply to traffic forwarded by the firewall policy. Source firewall.shaper.traffic-shaper.name.
traffic-shaper-reverse: type: str
traffic_shaper_reverse:
description: description:
- Traffic shaper to apply to response traffic received by the firewall policy. Source firewall.shaper.traffic-shaper.name. - Traffic shaper to apply to response traffic received by the firewall policy. Source firewall.shaper.traffic-shaper.name.
url-category: type: str
url_category:
description: description:
- IDs of one or more FortiGuard Web Filtering categories that this shaper applies traffic shaping to. - IDs of one or more FortiGuard Web Filtering categories that this shaper applies traffic shaping to.
type: list
suboptions: suboptions:
id: id:
description: description:
- URL category ID. - URL category ID.
required: true required: true
type: int
users: users:
description: description:
- Apply this traffic shaping policy to individual users that have authenticated with the FortiGate. - Apply this traffic shaping policy to individual users that have authenticated with the FortiGate.
type: list
suboptions: suboptions:
name: name:
description: description:
- User name. Source user.local.name. - User name. Source user.local.name.
required: true required: true
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -253,6 +304,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure shaping policies. - name: Configure shaping policies.
fortios_firewall_shaping_policy: fortios_firewall_shaping_policy:
@ -261,15 +313,15 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_shaping_policy: firewall_shaping_policy:
state: "present" app_category:
app-category:
- -
id: "4" id: "4"
application: application:
- -
id: "6" id: "6"
class-id: "7" class_id: "7"
comment: "Comments." comment: "Comments."
dstaddr: dstaddr:
- -
@ -284,22 +336,22 @@ EXAMPLES = '''
- -
name: "default_name_16 (source user.group.name)" name: "default_name_16 (source user.group.name)"
id: "17" id: "17"
internet-service: "enable" internet_service: "enable"
internet-service-custom: internet_service_custom:
- -
name: "default_name_20 (source firewall.internet-service-custom.name)" name: "default_name_20 (source firewall.internet-service-custom.name)"
internet-service-id: internet_service_id:
- -
id: "22 (source firewall.internet-service.id)" id: "22 (source firewall.internet-service.id)"
internet-service-src: "enable" internet_service_src: "enable"
internet-service-src-custom: internet_service_src_custom:
- -
name: "default_name_25 (source firewall.internet-service-custom.name)" name: "default_name_25 (source firewall.internet-service-custom.name)"
internet-service-src-id: internet_service_src_id:
- -
id: "27 (source firewall.internet-service.id)" id: "27 (source firewall.internet-service.id)"
ip-version: "4" ip_version: "4"
per-ip-shaper: "<your_own_value> (source firewall.shaper.per-ip-shaper.name)" per_ip_shaper: "<your_own_value> (source firewall.shaper.per-ip-shaper.name)"
schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)" schedule: "<your_own_value> (source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group.name)"
service: service:
- -
@ -311,9 +363,9 @@ EXAMPLES = '''
- -
name: "default_name_36 (source firewall.address6.name firewall.addrgrp6.name)" name: "default_name_36 (source firewall.address6.name firewall.addrgrp6.name)"
status: "enable" status: "enable"
traffic-shaper: "<your_own_value> (source firewall.shaper.traffic-shaper.name)" traffic_shaper: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
traffic-shaper-reverse: "<your_own_value> (source firewall.shaper.traffic-shaper.name)" traffic_shaper_reverse: "<your_own_value> (source firewall.shaper.traffic-shaper.name)"
url-category: url_category:
- -
id: "41" id: "41"
users: users:
@ -381,14 +433,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -396,19 +450,19 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_shaping_policy_data(json): def filter_firewall_shaping_policy_data(json):
option_list = ['app-category', 'application', 'class-id', option_list = ['app_category', 'application', 'class_id',
'comment', 'dstaddr', 'dstaddr6', 'comment', 'dstaddr', 'dstaddr6',
'dstintf', 'groups', 'id', 'dstintf', 'groups', 'id',
'internet-service', 'internet-service-custom', 'internet-service-id', 'internet_service', 'internet_service_custom', 'internet_service_id',
'internet-service-src', 'internet-service-src-custom', 'internet-service-src-id', 'internet_service_src', 'internet_service_src_custom', 'internet_service_src_id',
'ip-version', 'per-ip-shaper', 'schedule', 'ip_version', 'per_ip_shaper', 'schedule',
'service', 'srcaddr', 'srcaddr6', 'service', 'srcaddr', 'srcaddr6',
'status', 'traffic-shaper', 'traffic-shaper-reverse', 'status', 'traffic_shaper', 'traffic_shaper_reverse',
'url-category', 'users'] 'url_category', 'users']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -418,49 +472,67 @@ def filter_firewall_shaping_policy_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_shaping_policy(data, fos): def firewall_shaping_policy(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_shaping_policy_data = data['firewall_shaping_policy'] firewall_shaping_policy_data = data['firewall_shaping_policy']
filtered_data = filter_firewall_shaping_policy_data(firewall_shaping_policy_data) filtered_data = underscore_to_hyphen(filter_firewall_shaping_policy_data(firewall_shaping_policy_data))
if firewall_shaping_policy_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'shaping-policy', 'shaping-policy',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_shaping_policy_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'shaping-policy', 'shaping-policy',
mkey=filtered_data['id'], mkey=filtered_data['id'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_shaping_policy'] if data['firewall_shaping_policy']:
for method in methodlist: resp = firewall_shaping_policy(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_shaping_policy": { "firewall_shaping_policy": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "app_category": {"required": False, "type": "list",
"choices": ["present", "absent"]},
"app-category": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
@ -468,7 +540,7 @@ def main():
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"class-id": {"required": False, "type": "int"}, "class_id": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"dstaddr": {"required": False, "type": "list", "dstaddr": {"required": False, "type": "list",
"options": { "options": {
@ -487,29 +559,29 @@ def main():
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"id": {"required": True, "type": "int"}, "id": {"required": True, "type": "int"},
"internet-service": {"required": False, "type": "str", "internet_service": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"internet-service-custom": {"required": False, "type": "list", "internet_service_custom": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"internet-service-id": {"required": False, "type": "list", "internet_service_id": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"internet-service-src": {"required": False, "type": "str", "internet_service_src": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"internet-service-src-custom": {"required": False, "type": "list", "internet_service_src_custom": {"required": False, "type": "list",
"options": { "options": {
"name": {"required": True, "type": "str"} "name": {"required": True, "type": "str"}
}}, }},
"internet-service-src-id": {"required": False, "type": "list", "internet_service_src_id": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
"ip-version": {"required": False, "type": "str", "ip_version": {"required": False, "type": "str",
"choices": ["4", "6"]}, "choices": ["4", "6"]},
"per-ip-shaper": {"required": False, "type": "str"}, "per_ip_shaper": {"required": False, "type": "str"},
"schedule": {"required": False, "type": "str"}, "schedule": {"required": False, "type": "str"},
"service": {"required": False, "type": "list", "service": {"required": False, "type": "list",
"options": { "options": {
@ -525,9 +597,9 @@ def main():
}}, }},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"traffic-shaper": {"required": False, "type": "str"}, "traffic_shaper": {"required": False, "type": "str"},
"traffic-shaper-reverse": {"required": False, "type": "str"}, "traffic_shaper_reverse": {"required": False, "type": "str"},
"url-category": {"required": False, "type": "list", "url_category": {"required": False, "type": "list",
"options": { "options": {
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
}}, }},
@ -542,15 +614,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_shaping_profile module: fortios_firewall_shaping_profile
short_description: Configure shaping profiles in Fortinet's FortiOS and FortiGate. short_description: Configure shaping profiles in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and shaping_profile category. user to set and modify firewall feature and shaping_profile category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,70 +41,91 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_shaping_profile: firewall_shaping_profile:
description: description:
- Configure shaping profiles. - Configure shaping profiles.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
comment: comment:
description: description:
- Comment. - Comment.
default-class-id: type: str
default_class_id:
description: description:
- Default class ID to handle unclassified packets (including all local traffic). - Default class ID to handle unclassified packets (including all local traffic).
profile-name: type: int
profile_name:
description: description:
- Shaping profile name. - Shaping profile name.
required: true type: str
shaping-entries: shaping_entries:
description: description:
- Define shaping entries of this shaping profile. - Define shaping entries of this shaping profile.
type: list
suboptions: suboptions:
class-id: class_id:
description: description:
- Class ID. - Class ID.
guaranteed-bandwidth-percentage: type: int
guaranteed_bandwidth_percentage:
description: description:
- Guaranteed bandwith in percentage. - Guaranteed bandwith in percentage.
type: int
id: id:
description: description:
- ID number. - ID number.
required: true required: true
maximum-bandwidth-percentage: type: int
maximum_bandwidth_percentage:
description: description:
- Maximum bandwith in percentage. - Maximum bandwith in percentage.
type: int
priority: priority:
description: description:
- Priority. - Priority.
type: str
choices: choices:
- high - high
- medium - medium
@ -121,6 +139,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure shaping profiles. - name: Configure shaping profiles.
fortios_firewall_shaping_profile: fortios_firewall_shaping_profile:
@ -129,17 +148,17 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_shaping_profile: firewall_shaping_profile:
state: "present"
comment: "Comment." comment: "Comment."
default-class-id: "4" default_class_id: "4"
profile-name: "<your_own_value>" profile_name: "<your_own_value>"
shaping-entries: shaping_entries:
- -
class-id: "7" class_id: "7"
guaranteed-bandwidth-percentage: "8" guaranteed_bandwidth_percentage: "8"
id: "9" id: "9"
maximum-bandwidth-percentage: "10" maximum_bandwidth_percentage: "10"
priority: "high" priority: "high"
''' '''
@ -203,14 +222,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -218,12 +239,12 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_shaping_profile_data(json): def filter_firewall_shaping_profile_data(json):
option_list = ['comment', 'default-class-id', 'profile-name', option_list = ['comment', 'default_class_id', 'profile_name',
'shaping-entries'] 'shaping_entries']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -233,57 +254,75 @@ def filter_firewall_shaping_profile_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_shaping_profile(data, fos): def firewall_shaping_profile(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_shaping_profile_data = data['firewall_shaping_profile'] firewall_shaping_profile_data = data['firewall_shaping_profile']
filtered_data = filter_firewall_shaping_profile_data(firewall_shaping_profile_data) filtered_data = underscore_to_hyphen(filter_firewall_shaping_profile_data(firewall_shaping_profile_data))
if firewall_shaping_profile_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'shaping-profile', 'shaping-profile',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_shaping_profile_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'shaping-profile', 'shaping-profile',
mkey=filtered_data['profile-name'], mkey=filtered_data['profile-name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_shaping_profile'] if data['firewall_shaping_profile']:
for method in methodlist: resp = firewall_shaping_profile(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_shaping_profile": { "firewall_shaping_profile": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"default-class-id": {"required": False, "type": "int"}, "default_class_id": {"required": False, "type": "int"},
"profile-name": {"required": True, "type": "str"}, "profile_name": {"required": False, "type": "str"},
"shaping-entries": {"required": False, "type": "list", "shaping_entries": {"required": False, "type": "list",
"options": { "options": {
"class-id": {"required": False, "type": "int"}, "class_id": {"required": False, "type": "int"},
"guaranteed-bandwidth-percentage": {"required": False, "type": "int"}, "guaranteed_bandwidth_percentage": {"required": False, "type": "int"},
"id": {"required": True, "type": "int"}, "id": {"required": True, "type": "int"},
"maximum-bandwidth-percentage": {"required": False, "type": "int"}, "maximum_bandwidth_percentage": {"required": False, "type": "int"},
"priority": {"required": False, "type": "str", "priority": {"required": False, "type": "str",
"choices": ["high", "medium", "low"]} "choices": ["high", "medium", "low"]}
}} }}
@ -294,15 +333,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_sniffer module: fortios_firewall_sniffer
short_description: Configure sniffer in Fortinet's FortiOS and FortiGate. short_description: Configure sniffer in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and sniffer category. user to set and modify firewall feature and sniffer category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,53 +41,69 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_sniffer: firewall_sniffer:
description: description:
- Configure sniffer. - Configure sniffer.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
anomaly: anomaly:
description: description:
- Configuration method to edit Denial of Service (DoS) anomaly settings. - Configuration method to edit Denial of Service (DoS) anomaly settings.
type: list
suboptions: suboptions:
action: action:
description: description:
- Action taken when the threshold is reached. - Action taken when the threshold is reached.
type: str
choices: choices:
- pass - pass
- block - block
log: log:
description: description:
- Enable/disable anomaly logging. - Enable/disable anomaly logging.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -98,151 +111,184 @@ options:
description: description:
- Anomaly name. - Anomaly name.
required: true required: true
type: str
quarantine: quarantine:
description: description:
- Quarantine method. - Quarantine method.
type: str
choices: choices:
- none - none
- attacker - attacker
quarantine-expiry: quarantine_expiry:
description: description:
- Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m, default = 5m). Requires quarantine set to attacker. - Duration of quarantine. (Format ###d##h##m, minimum 1m, maximum 364d23h59m, default = 5m). Requires quarantine set to attacker.
quarantine-log: type: str
quarantine_log:
description: description:
- Enable/disable quarantine logging. - Enable/disable quarantine logging.
type: str
choices: choices:
- disable - disable
- enable - enable
status: status:
description: description:
- Enable/disable this anomaly. - Enable/disable this anomaly.
type: str
choices: choices:
- disable - disable
- enable - enable
threshold: threshold:
description: description:
- Anomaly threshold. Number of detected instances per minute that triggers the anomaly action. - Anomaly threshold. Number of detected instances per minute that triggers the anomaly action.
type: int
threshold(default): threshold(default):
description: description:
- Number of detected instances per minute which triggers action (1 - 2147483647, default = 1000). Note that each anomaly has a - Number of detected instances per minute which triggers action (1 - 2147483647, default = 1000). Note that each anomaly has a
different threshold value assigned to it. different threshold value assigned to it.
application-list: type: int
application_list:
description: description:
- Name of an existing application list. Source application.list.name. - Name of an existing application list. Source application.list.name.
application-list-status: type: str
application_list_status:
description: description:
- Enable/disable application control profile. - Enable/disable application control profile.
type: str
choices: choices:
- enable - enable
- disable - disable
av-profile: av_profile:
description: description:
- Name of an existing antivirus profile. Source antivirus.profile.name. - Name of an existing antivirus profile. Source antivirus.profile.name.
av-profile-status: type: str
av_profile_status:
description: description:
- Enable/disable antivirus profile. - Enable/disable antivirus profile.
type: str
choices: choices:
- enable - enable
- disable - disable
dlp-sensor: dlp_sensor:
description: description:
- Name of an existing DLP sensor. Source dlp.sensor.name. - Name of an existing DLP sensor. Source dlp.sensor.name.
dlp-sensor-status: type: str
dlp_sensor_status:
description: description:
- Enable/disable DLP sensor. - Enable/disable DLP sensor.
type: str
choices: choices:
- enable - enable
- disable - disable
dsri: dsri:
description: description:
- Enable/disable DSRI. - Enable/disable DSRI.
type: str
choices: choices:
- enable - enable
- disable - disable
host: host:
description: description:
- "Hosts to filter for in sniffer traffic (Format examples: 1.1.1.1, 2.2.2.0/24, 3.3.3.3/255.255.255.0, 4.4.4.0-4.4.4.240)." - "Hosts to filter for in sniffer traffic (Format examples: 1.1.1.1, 2.2.2.0/24, 3.3.3.3/255.255.255.0, 4.4.4.0-4.4.4.240)."
type: str
id: id:
description: description:
- Sniffer ID. - Sniffer ID.
required: true required: true
type: int
interface: interface:
description: description:
- Interface name that traffic sniffing will take place on. Source system.interface.name. - Interface name that traffic sniffing will take place on. Source system.interface.name.
ips-dos-status: type: str
ips_dos_status:
description: description:
- Enable/disable IPS DoS anomaly detection. - Enable/disable IPS DoS anomaly detection.
type: str
choices: choices:
- enable - enable
- disable - disable
ips-sensor: ips_sensor:
description: description:
- Name of an existing IPS sensor. Source ips.sensor.name. - Name of an existing IPS sensor. Source ips.sensor.name.
ips-sensor-status: type: str
ips_sensor_status:
description: description:
- Enable/disable IPS sensor. - Enable/disable IPS sensor.
type: str
choices: choices:
- enable - enable
- disable - disable
ipv6: ipv6:
description: description:
- Enable/disable sniffing IPv6 packets. - Enable/disable sniffing IPv6 packets.
type: str
choices: choices:
- enable - enable
- disable - disable
logtraffic: logtraffic:
description: description:
- Either log all sessions, only sessions that have a security profile applied, or disable all logging for this policy. - Either log all sessions, only sessions that have a security profile applied, or disable all logging for this policy.
type: str
choices: choices:
- all - all
- utm - utm
- disable - disable
max-packet-count: max_packet_count:
description: description:
- Maximum packet count (1 - 1000000, default = 10000). - Maximum packet count (1 - 1000000, default = 10000).
non-ip: type: int
non_ip:
description: description:
- Enable/disable sniffing non-IP packets. - Enable/disable sniffing non-IP packets.
type: str
choices: choices:
- enable - enable
- disable - disable
port: port:
description: description:
- "Ports to sniff (Format examples: 10, :20, 30:40, 50-, 100-200)." - "Ports to sniff (Format examples: 10, :20, 30:40, 50-, 100-200)."
type: str
protocol: protocol:
description: description:
- Integer value for the protocol type as defined by IANA (0 - 255). - Integer value for the protocol type as defined by IANA (0 - 255).
scan-botnet-connections: type: str
scan_botnet_connections:
description: description:
- Enable/disable scanning of connections to Botnet servers. - Enable/disable scanning of connections to Botnet servers.
type: str
choices: choices:
- disable - disable
- block - block
- monitor - monitor
spamfilter-profile: spamfilter_profile:
description: description:
- Name of an existing spam filter profile. Source spamfilter.profile.name. - Name of an existing spam filter profile. Source spamfilter.profile.name.
spamfilter-profile-status: type: str
spamfilter_profile_status:
description: description:
- Enable/disable spam filter. - Enable/disable spam filter.
type: str
choices: choices:
- enable - enable
- disable - disable
status: status:
description: description:
- Enable/disable the active status of the sniffer. - Enable/disable the active status of the sniffer.
type: str
choices: choices:
- enable - enable
- disable - disable
vlan: vlan:
description: description:
- List of VLANs to sniff. - List of VLANs to sniff.
webfilter-profile: type: str
webfilter_profile:
description: description:
- Name of an existing web filter profile. Source webfilter.profile.name. - Name of an existing web filter profile. Source webfilter.profile.name.
webfilter-profile-status: type: str
webfilter_profile_status:
description: description:
- Enable/disable web filter profile. - Enable/disable web filter profile.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -255,6 +301,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure sniffer. - name: Configure sniffer.
fortios_firewall_sniffer: fortios_firewall_sniffer:
@ -263,45 +310,45 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_sniffer: firewall_sniffer:
state: "present"
anomaly: anomaly:
- -
action: "pass" action: "pass"
log: "enable" log: "enable"
name: "default_name_6" name: "default_name_6"
quarantine: "none" quarantine: "none"
quarantine-expiry: "<your_own_value>" quarantine_expiry: "<your_own_value>"
quarantine-log: "disable" quarantine_log: "disable"
status: "disable" status: "disable"
threshold: "11" threshold: "11"
threshold(default): "12" threshold(default): "12"
application-list: "<your_own_value> (source application.list.name)" application_list: "<your_own_value> (source application.list.name)"
application-list-status: "enable" application_list_status: "enable"
av-profile: "<your_own_value> (source antivirus.profile.name)" av_profile: "<your_own_value> (source antivirus.profile.name)"
av-profile-status: "enable" av_profile_status: "enable"
dlp-sensor: "<your_own_value> (source dlp.sensor.name)" dlp_sensor: "<your_own_value> (source dlp.sensor.name)"
dlp-sensor-status: "enable" dlp_sensor_status: "enable"
dsri: "enable" dsri: "enable"
host: "myhostname" host: "myhostname"
id: "21" id: "21"
interface: "<your_own_value> (source system.interface.name)" interface: "<your_own_value> (source system.interface.name)"
ips-dos-status: "enable" ips_dos_status: "enable"
ips-sensor: "<your_own_value> (source ips.sensor.name)" ips_sensor: "<your_own_value> (source ips.sensor.name)"
ips-sensor-status: "enable" ips_sensor_status: "enable"
ipv6: "enable" ipv6: "enable"
logtraffic: "all" logtraffic: "all"
max-packet-count: "28" max_packet_count: "28"
non-ip: "enable" non_ip: "enable"
port: "<your_own_value>" port: "<your_own_value>"
protocol: "<your_own_value>" protocol: "<your_own_value>"
scan-botnet-connections: "disable" scan_botnet_connections: "disable"
spamfilter-profile: "<your_own_value> (source spamfilter.profile.name)" spamfilter_profile: "<your_own_value> (source spamfilter.profile.name)"
spamfilter-profile-status: "enable" spamfilter_profile_status: "enable"
status: "enable" status: "enable"
vlan: "<your_own_value>" vlan: "<your_own_value>"
webfilter-profile: "<your_own_value> (source webfilter.profile.name)" webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
webfilter-profile-status: "enable" webfilter_profile_status: "enable"
''' '''
RETURN = ''' RETURN = '''
@ -364,14 +411,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -379,19 +428,19 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_sniffer_data(json): def filter_firewall_sniffer_data(json):
option_list = ['anomaly', 'application-list', 'application-list-status', option_list = ['anomaly', 'application_list', 'application_list_status',
'av-profile', 'av-profile-status', 'dlp-sensor', 'av_profile', 'av_profile_status', 'dlp_sensor',
'dlp-sensor-status', 'dsri', 'host', 'dlp_sensor_status', 'dsri', 'host',
'id', 'interface', 'ips-dos-status', 'id', 'interface', 'ips_dos_status',
'ips-sensor', 'ips-sensor-status', 'ipv6', 'ips_sensor', 'ips_sensor_status', 'ipv6',
'logtraffic', 'max-packet-count', 'non-ip', 'logtraffic', 'max_packet_count', 'non_ip',
'port', 'protocol', 'scan-botnet-connections', 'port', 'protocol', 'scan_botnet_connections',
'spamfilter-profile', 'spamfilter-profile-status', 'status', 'spamfilter_profile', 'spamfilter_profile_status', 'status',
'vlan', 'webfilter-profile', 'webfilter-profile-status'] 'vlan', 'webfilter_profile', 'webfilter_profile_status']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -401,48 +450,66 @@ def filter_firewall_sniffer_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_sniffer(data, fos): def firewall_sniffer(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_sniffer_data = data['firewall_sniffer'] firewall_sniffer_data = data['firewall_sniffer']
filtered_data = filter_firewall_sniffer_data(firewall_sniffer_data) filtered_data = underscore_to_hyphen(filter_firewall_sniffer_data(firewall_sniffer_data))
if firewall_sniffer_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'sniffer', 'sniffer',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_sniffer_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'sniffer', 'sniffer',
mkey=filtered_data['id'], mkey=filtered_data['id'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_sniffer'] if data['firewall_sniffer']:
for method in methodlist: resp = firewall_sniffer(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_sniffer": { "firewall_sniffer": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"anomaly": {"required": False, "type": "list", "anomaly": {"required": False, "type": "list",
"options": { "options": {
"action": {"required": False, "type": "str", "action": {"required": False, "type": "str",
@ -452,52 +519,52 @@ def main():
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"quarantine": {"required": False, "type": "str", "quarantine": {"required": False, "type": "str",
"choices": ["none", "attacker"]}, "choices": ["none", "attacker"]},
"quarantine-expiry": {"required": False, "type": "str"}, "quarantine_expiry": {"required": False, "type": "str"},
"quarantine-log": {"required": False, "type": "str", "quarantine_log": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"threshold": {"required": False, "type": "int"}, "threshold": {"required": False, "type": "int"},
"threshold(default)": {"required": False, "type": "int"} "threshold(default)": {"required": False, "type": "int"}
}}, }},
"application-list": {"required": False, "type": "str"}, "application_list": {"required": False, "type": "str"},
"application-list-status": {"required": False, "type": "str", "application_list_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"av-profile": {"required": False, "type": "str"}, "av_profile": {"required": False, "type": "str"},
"av-profile-status": {"required": False, "type": "str", "av_profile_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"dlp-sensor": {"required": False, "type": "str"}, "dlp_sensor": {"required": False, "type": "str"},
"dlp-sensor-status": {"required": False, "type": "str", "dlp_sensor_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"dsri": {"required": False, "type": "str", "dsri": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"host": {"required": False, "type": "str"}, "host": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"}, "id": {"required": True, "type": "int"},
"interface": {"required": False, "type": "str"}, "interface": {"required": False, "type": "str"},
"ips-dos-status": {"required": False, "type": "str", "ips_dos_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"ips-sensor": {"required": False, "type": "str"}, "ips_sensor": {"required": False, "type": "str"},
"ips-sensor-status": {"required": False, "type": "str", "ips_sensor_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"ipv6": {"required": False, "type": "str", "ipv6": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"logtraffic": {"required": False, "type": "str", "logtraffic": {"required": False, "type": "str",
"choices": ["all", "utm", "disable"]}, "choices": ["all", "utm", "disable"]},
"max-packet-count": {"required": False, "type": "int"}, "max_packet_count": {"required": False, "type": "int"},
"non-ip": {"required": False, "type": "str", "non_ip": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"port": {"required": False, "type": "str"}, "port": {"required": False, "type": "str"},
"protocol": {"required": False, "type": "str"}, "protocol": {"required": False, "type": "str"},
"scan-botnet-connections": {"required": False, "type": "str", "scan_botnet_connections": {"required": False, "type": "str",
"choices": ["disable", "block", "monitor"]}, "choices": ["disable", "block", "monitor"]},
"spamfilter-profile": {"required": False, "type": "str"}, "spamfilter_profile": {"required": False, "type": "str"},
"spamfilter-profile-status": {"required": False, "type": "str", "spamfilter_profile_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"vlan": {"required": False, "type": "str"}, "vlan": {"required": False, "type": "str"},
"webfilter-profile": {"required": False, "type": "str"}, "webfilter_profile": {"required": False, "type": "str"},
"webfilter-profile-status": {"required": False, "type": "str", "webfilter_profile_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]} "choices": ["enable", "disable"]}
} }
@ -506,15 +573,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_ssh_host_key module: fortios_firewall_ssh_host_key
short_description: SSH proxy host public keys in Fortinet's FortiOS and FortiGate. short_description: SSH proxy host public keys in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_ssh feature and host_key category. user to set and modify firewall_ssh feature and host_key category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,53 +41,70 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_ssh_host_key: firewall_ssh_host_key:
description: description:
- SSH proxy host public keys. - SSH proxy host public keys.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
hostname: hostname:
description: description:
- Hostname of the SSH server. - Hostname of the SSH server.
type: str
ip: ip:
description: description:
- IP address of the SSH server. - IP address of the SSH server.
type: str
name: name:
description: description:
- SSH public key name. - SSH public key name.
required: true required: true
type: str
nid: nid:
description: description:
- Set the nid of the ECDSA key. - Set the nid of the ECDSA key.
type: str
choices: choices:
- 256 - 256
- 384 - 384
@ -98,18 +112,22 @@ options:
port: port:
description: description:
- Port of the SSH server. - Port of the SSH server.
public-key: type: int
public_key:
description: description:
- SSH public key. - SSH public key.
type: str
status: status:
description: description:
- Set the trust status of the public key. - Set the trust status of the public key.
type: str
choices: choices:
- trusted - trusted
- revoked - revoked
type: type:
description: description:
- Set the type of the public key. - Set the type of the public key.
type: str
choices: choices:
- RSA - RSA
- DSA - DSA
@ -128,6 +146,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: SSH proxy host public keys. - name: SSH proxy host public keys.
fortios_firewall_ssh_host_key: fortios_firewall_ssh_host_key:
@ -136,14 +155,14 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_ssh_host_key: firewall_ssh_host_key:
state: "present"
hostname: "myhostname" hostname: "myhostname"
ip: "<your_own_value>" ip: "<your_own_value>"
name: "default_name_5" name: "default_name_5"
nid: "256" nid: "256"
port: "7" port: "7"
public-key: "<your_own_value>" public_key: "<your_own_value>"
status: "trusted" status: "trusted"
type: "RSA" type: "RSA"
''' '''
@ -208,14 +227,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -223,12 +244,12 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_ssh_host_key_data(json): def filter_firewall_ssh_host_key_data(json):
option_list = ['hostname', 'ip', 'name', option_list = ['hostname', 'ip', 'name',
'nid', 'port', 'public-key', 'nid', 'port', 'public_key',
'status', 'type'] 'status', 'type']
dictionary = {} dictionary = {}
@ -239,55 +260,73 @@ def filter_firewall_ssh_host_key_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_ssh_host_key(data, fos): def firewall_ssh_host_key(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_ssh_host_key_data = data['firewall_ssh_host_key'] firewall_ssh_host_key_data = data['firewall_ssh_host_key']
filtered_data = filter_firewall_ssh_host_key_data(firewall_ssh_host_key_data) filtered_data = underscore_to_hyphen(filter_firewall_ssh_host_key_data(firewall_ssh_host_key_data))
if firewall_ssh_host_key_data['state'] == "present":
if state == "present":
return fos.set('firewall.ssh', return fos.set('firewall.ssh',
'host-key', 'host-key',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_ssh_host_key_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.ssh', return fos.delete('firewall.ssh',
'host-key', 'host-key',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_ssh(data, fos): def fortios_firewall_ssh(data, fos):
login(data)
methodlist = ['firewall_ssh_host_key'] if data['firewall_ssh_host_key']:
for method in methodlist: resp = firewall_ssh_host_key(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_ssh_host_key": { "firewall_ssh_host_key": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"hostname": {"required": False, "type": "str"}, "hostname": {"required": False, "type": "str"},
"ip": {"required": False, "type": "str"}, "ip": {"required": False, "type": "str"},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"nid": {"required": False, "type": "str", "nid": {"required": False, "type": "str",
"choices": ["256", "384", "521"]}, "choices": ["256", "384", "521"]},
"port": {"required": False, "type": "int"}, "port": {"required": False, "type": "int"},
"public-key": {"required": False, "type": "str"}, "public_key": {"required": False, "type": "str"},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["trusted", "revoked"]}, "choices": ["trusted", "revoked"]},
"type": {"required": False, "type": "str", "type": {"required": False, "type": "str",
@ -301,15 +340,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_ssh_local_ca module: fortios_firewall_ssh_local_ca
short_description: SSH proxy local CA in Fortinet's FortiOS and FortiGate. short_description: SSH proxy local CA in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_ssh feature and local_ca category. user to set and modify firewall_ssh feature and local_ca category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,56 +41,74 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_ssh_local_ca: firewall_ssh_local_ca:
description: description:
- SSH proxy local CA. - SSH proxy local CA.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
name: name:
description: description:
- SSH proxy local CA name. - SSH proxy local CA name.
required: true required: true
type: str
password: password:
description: description:
- Password for SSH private key. - Password for SSH private key.
private-key: type: str
private_key:
description: description:
- SSH proxy private key, encrypted with a password. - SSH proxy private key, encrypted with a password.
public-key: type: str
public_key:
description: description:
- SSH proxy public key. - SSH proxy public key.
type: str
source: source:
description: description:
- SSH proxy local CA source type. - SSH proxy local CA source type.
type: str
choices: choices:
- built-in - built-in
- user - user
@ -106,6 +121,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: SSH proxy local CA. - name: SSH proxy local CA.
fortios_firewall_ssh_local_ca: fortios_firewall_ssh_local_ca:
@ -114,12 +130,12 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_ssh_local_ca: firewall_ssh_local_ca:
state: "present"
name: "default_name_3" name: "default_name_3"
password: "<your_own_value>" password: "<your_own_value>"
private-key: "<your_own_value>" private_key: "<your_own_value>"
public-key: "<your_own_value>" public_key: "<your_own_value>"
source: "built-in" source: "built-in"
''' '''
@ -183,14 +199,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -198,12 +216,12 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_ssh_local_ca_data(json): def filter_firewall_ssh_local_ca_data(json):
option_list = ['name', 'password', 'private-key', option_list = ['name', 'password', 'private_key',
'public-key', 'source'] 'public_key', 'source']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -213,52 +231,70 @@ def filter_firewall_ssh_local_ca_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_ssh_local_ca(data, fos): def firewall_ssh_local_ca(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_ssh_local_ca_data = data['firewall_ssh_local_ca'] firewall_ssh_local_ca_data = data['firewall_ssh_local_ca']
filtered_data = filter_firewall_ssh_local_ca_data(firewall_ssh_local_ca_data) filtered_data = underscore_to_hyphen(filter_firewall_ssh_local_ca_data(firewall_ssh_local_ca_data))
if firewall_ssh_local_ca_data['state'] == "present":
if state == "present":
return fos.set('firewall.ssh', return fos.set('firewall.ssh',
'local-ca', 'local-ca',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_ssh_local_ca_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.ssh', return fos.delete('firewall.ssh',
'local-ca', 'local-ca',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_ssh(data, fos): def fortios_firewall_ssh(data, fos):
login(data)
methodlist = ['firewall_ssh_local_ca'] if data['firewall_ssh_local_ca']:
for method in methodlist: resp = firewall_ssh_local_ca(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_ssh_local_ca": { "firewall_ssh_local_ca": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"password": {"required": False, "type": "str"}, "password": {"required": False, "type": "str"},
"private-key": {"required": False, "type": "str"}, "private_key": {"required": False, "type": "str"},
"public-key": {"required": False, "type": "str"}, "public_key": {"required": False, "type": "str"},
"source": {"required": False, "type": "str", "source": {"required": False, "type": "str",
"choices": ["built-in", "user"]} "choices": ["built-in", "user"]}
@ -268,15 +304,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_ssh_local_key module: fortios_firewall_ssh_local_key
short_description: SSH proxy local keys in Fortinet's FortiOS and FortiGate. short_description: SSH proxy local keys in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_ssh feature and local_key category. user to set and modify firewall_ssh feature and local_key category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,56 +41,74 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_ssh_local_key: firewall_ssh_local_key:
description: description:
- SSH proxy local keys. - SSH proxy local keys.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
name: name:
description: description:
- SSH proxy local key name. - SSH proxy local key name.
required: true required: true
type: str
password: password:
description: description:
- Password for SSH private key. - Password for SSH private key.
private-key: type: str
private_key:
description: description:
- SSH proxy private key, encrypted with a password. - SSH proxy private key, encrypted with a password.
public-key: type: str
public_key:
description: description:
- SSH proxy public key. - SSH proxy public key.
type: str
source: source:
description: description:
- SSH proxy local key source type. - SSH proxy local key source type.
type: str
choices: choices:
- built-in - built-in
- user - user
@ -106,6 +121,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: SSH proxy local keys. - name: SSH proxy local keys.
fortios_firewall_ssh_local_key: fortios_firewall_ssh_local_key:
@ -114,12 +130,12 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_ssh_local_key: firewall_ssh_local_key:
state: "present"
name: "default_name_3" name: "default_name_3"
password: "<your_own_value>" password: "<your_own_value>"
private-key: "<your_own_value>" private_key: "<your_own_value>"
public-key: "<your_own_value>" public_key: "<your_own_value>"
source: "built-in" source: "built-in"
''' '''
@ -183,14 +199,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -198,12 +216,12 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_ssh_local_key_data(json): def filter_firewall_ssh_local_key_data(json):
option_list = ['name', 'password', 'private-key', option_list = ['name', 'password', 'private_key',
'public-key', 'source'] 'public_key', 'source']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -213,52 +231,70 @@ def filter_firewall_ssh_local_key_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_ssh_local_key(data, fos): def firewall_ssh_local_key(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_ssh_local_key_data = data['firewall_ssh_local_key'] firewall_ssh_local_key_data = data['firewall_ssh_local_key']
filtered_data = filter_firewall_ssh_local_key_data(firewall_ssh_local_key_data) filtered_data = underscore_to_hyphen(filter_firewall_ssh_local_key_data(firewall_ssh_local_key_data))
if firewall_ssh_local_key_data['state'] == "present":
if state == "present":
return fos.set('firewall.ssh', return fos.set('firewall.ssh',
'local-key', 'local-key',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_ssh_local_key_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.ssh', return fos.delete('firewall.ssh',
'local-key', 'local-key',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_ssh(data, fos): def fortios_firewall_ssh(data, fos):
login(data)
methodlist = ['firewall_ssh_local_key'] if data['firewall_ssh_local_key']:
for method in methodlist: resp = firewall_ssh_local_key(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_ssh_local_key": { "firewall_ssh_local_key": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"password": {"required": False, "type": "str"}, "password": {"required": False, "type": "str"},
"private-key": {"required": False, "type": "str"}, "private_key": {"required": False, "type": "str"},
"public-key": {"required": False, "type": "str"}, "public_key": {"required": False, "type": "str"},
"source": {"required": False, "type": "str", "source": {"required": False, "type": "str",
"choices": ["built-in", "user"]} "choices": ["built-in", "user"]}
@ -268,15 +304,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_ssh_setting module: fortios_firewall_ssh_setting
short_description: SSH proxy settings in Fortinet's FortiOS and FortiGate. short_description: SSH proxy settings in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_ssh feature and setting category. user to set and modify firewall_ssh feature and setting category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,64 +41,83 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
firewall_ssh_setting: firewall_ssh_setting:
description: description:
- SSH proxy settings. - SSH proxy settings.
default: null default: null
type: dict
suboptions: suboptions:
caname: caname:
description: description:
- CA certificate used by SSH Inspection. Source firewall.ssh.local-ca.name. - CA certificate used by SSH Inspection. Source firewall.ssh.local-ca.name.
host-trusted-checking: type: str
host_trusted_checking:
description: description:
- Enable/disable host trusted checking. - Enable/disable host trusted checking.
type: str
choices: choices:
- enable - enable
- disable - disable
hostkey-dsa1024: hostkey_dsa1024:
description: description:
- DSA certificate used by SSH proxy. Source firewall.ssh.local-key.name. - DSA certificate used by SSH proxy. Source firewall.ssh.local-key.name.
hostkey-ecdsa256: type: str
hostkey_ecdsa256:
description: description:
- ECDSA nid256 certificate used by SSH proxy. Source firewall.ssh.local-key.name. - ECDSA nid256 certificate used by SSH proxy. Source firewall.ssh.local-key.name.
hostkey-ecdsa384: type: str
hostkey_ecdsa384:
description: description:
- ECDSA nid384 certificate used by SSH proxy. Source firewall.ssh.local-key.name. - ECDSA nid384 certificate used by SSH proxy. Source firewall.ssh.local-key.name.
hostkey-ecdsa521: type: str
hostkey_ecdsa521:
description: description:
- ECDSA nid384 certificate used by SSH proxy. Source firewall.ssh.local-key.name. - ECDSA nid384 certificate used by SSH proxy. Source firewall.ssh.local-key.name.
hostkey-ed25519: type: str
hostkey_ed25519:
description: description:
- ED25519 hostkey used by SSH proxy. Source firewall.ssh.local-key.name. - ED25519 hostkey used by SSH proxy. Source firewall.ssh.local-key.name.
hostkey-rsa2048: type: str
hostkey_rsa2048:
description: description:
- RSA certificate used by SSH proxy. Source firewall.ssh.local-key.name. - RSA certificate used by SSH proxy. Source firewall.ssh.local-key.name.
untrusted-caname: type: str
untrusted_caname:
description: description:
- Untrusted CA certificate used by SSH Inspection. Source firewall.ssh.local-ca.name. - Untrusted CA certificate used by SSH Inspection. Source firewall.ssh.local-ca.name.
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -111,6 +127,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: SSH proxy settings. - name: SSH proxy settings.
fortios_firewall_ssh_setting: fortios_firewall_ssh_setting:
@ -121,14 +138,14 @@ EXAMPLES = '''
https: "False" https: "False"
firewall_ssh_setting: firewall_ssh_setting:
caname: "<your_own_value> (source firewall.ssh.local-ca.name)" caname: "<your_own_value> (source firewall.ssh.local-ca.name)"
host-trusted-checking: "enable" host_trusted_checking: "enable"
hostkey-dsa1024: "myhostname (source firewall.ssh.local-key.name)" hostkey_dsa1024: "myhostname (source firewall.ssh.local-key.name)"
hostkey-ecdsa256: "myhostname (source firewall.ssh.local-key.name)" hostkey_ecdsa256: "myhostname (source firewall.ssh.local-key.name)"
hostkey-ecdsa384: "myhostname (source firewall.ssh.local-key.name)" hostkey_ecdsa384: "myhostname (source firewall.ssh.local-key.name)"
hostkey-ecdsa521: "myhostname (source firewall.ssh.local-key.name)" hostkey_ecdsa521: "myhostname (source firewall.ssh.local-key.name)"
hostkey-ed25519: "myhostname (source firewall.ssh.local-key.name)" hostkey_ed25519: "myhostname (source firewall.ssh.local-key.name)"
hostkey-rsa2048: "myhostname (source firewall.ssh.local-key.name)" hostkey_rsa2048: "myhostname (source firewall.ssh.local-key.name)"
untrusted-caname: "<your_own_value> (source firewall.ssh.local-ca.name)" untrusted_caname: "<your_own_value> (source firewall.ssh.local-ca.name)"
''' '''
RETURN = ''' RETURN = '''
@ -191,14 +208,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -206,13 +225,13 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_ssh_setting_data(json): def filter_firewall_ssh_setting_data(json):
option_list = ['caname', 'host-trusted-checking', 'hostkey-dsa1024', option_list = ['caname', 'host_trusted_checking', 'hostkey_dsa1024',
'hostkey-ecdsa256', 'hostkey-ecdsa384', 'hostkey-ecdsa521', 'hostkey_ecdsa256', 'hostkey_ecdsa384', 'hostkey_ecdsa521',
'hostkey-ed25519', 'hostkey-rsa2048', 'untrusted-caname'] 'hostkey_ed25519', 'hostkey_rsa2048', 'untrusted_caname']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -222,49 +241,66 @@ def filter_firewall_ssh_setting_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_ssh_setting(data, fos): def firewall_ssh_setting(data, fos):
vdom = data['vdom'] vdom = data['vdom']
firewall_ssh_setting_data = data['firewall_ssh_setting'] firewall_ssh_setting_data = data['firewall_ssh_setting']
filtered_data = filter_firewall_ssh_setting_data(firewall_ssh_setting_data) filtered_data = underscore_to_hyphen(filter_firewall_ssh_setting_data(firewall_ssh_setting_data))
return fos.set('firewall.ssh', return fos.set('firewall.ssh',
'setting', 'setting',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_ssh(data, fos): def fortios_firewall_ssh(data, fos):
login(data)
methodlist = ['firewall_ssh_setting'] if data['firewall_ssh_setting']:
for method in methodlist: resp = firewall_ssh_setting(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"firewall_ssh_setting": { "firewall_ssh_setting": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"caname": {"required": False, "type": "str"}, "caname": {"required": False, "type": "str"},
"host-trusted-checking": {"required": False, "type": "str", "host_trusted_checking": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"hostkey-dsa1024": {"required": False, "type": "str"}, "hostkey_dsa1024": {"required": False, "type": "str"},
"hostkey-ecdsa256": {"required": False, "type": "str"}, "hostkey_ecdsa256": {"required": False, "type": "str"},
"hostkey-ecdsa384": {"required": False, "type": "str"}, "hostkey_ecdsa384": {"required": False, "type": "str"},
"hostkey-ecdsa521": {"required": False, "type": "str"}, "hostkey_ecdsa521": {"required": False, "type": "str"},
"hostkey-ed25519": {"required": False, "type": "str"}, "hostkey_ed25519": {"required": False, "type": "str"},
"hostkey-rsa2048": {"required": False, "type": "str"}, "hostkey_rsa2048": {"required": False, "type": "str"},
"untrusted-caname": {"required": False, "type": "str"} "untrusted_caname": {"required": False, "type": "str"}
} }
} }
@ -272,15 +308,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_ssh(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_ssl_server module: fortios_firewall_ssl_server
short_description: Configure SSL servers in Fortinet's FortiOS and FortiGate. short_description: Configure SSL servers in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall feature and ssl_server category. user to set and modify firewall feature and ssl_server category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,113 +41,140 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
firewall_ssl_server: firewall_ssl_server:
description: description:
- Configure SSL servers. - Configure SSL servers.
default: null default: null
type: dict
suboptions: suboptions:
state: add_header_x_forwarded_proto:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
add-header-x-forwarded-proto:
description: description:
- Enable/disable adding an X-Forwarded-Proto header to forwarded requests. - Enable/disable adding an X-Forwarded-Proto header to forwarded requests.
type: str
choices: choices:
- enable - enable
- disable - disable
ip: ip:
description: description:
- IPv4 address of the SSL server. - IPv4 address of the SSL server.
mapped-port: type: str
mapped_port:
description: description:
- Mapped server service port (1 - 65535, default = 80). - Mapped server service port (1 - 65535).
type: int
name: name:
description: description:
- Server name. - Server name.
required: true required: true
type: str
port: port:
description: description:
- Server service port (1 - 65535, default = 443). - Server service port (1 - 65535).
ssl-algorithm: type: int
ssl_algorithm:
description: description:
- Relative strength of encryption algorithms accepted in negotiation. - Relative strength of encryption algorithms accepted in negotiation.
type: str
choices: choices:
- high - high
- medium - medium
- low - low
ssl-cert: ssl_cert:
description: description:
- Name of certificate for SSL connections to this server (default = "Fortinet_CA_SSL"). Source vpn.certificate.local.name. - Name of certificate for SSL connections to this server. Source vpn.certificate.local.name.
ssl-client-renegotiation: type: str
ssl_client_renegotiation:
description: description:
- Allow or block client renegotiation by server. - Allow or block client renegotiation by server.
type: str
choices: choices:
- allow - allow
- deny - deny
- secure - secure
ssl-dh-bits: ssl_dh_bits:
description: description:
- Bit-size of Diffie-Hellman (DH) prime used in DHE-RSA negotiation (default = 2048). - Bit-size of Diffie-Hellman (DH) prime used in DHE-RSA negotiation.
type: str
choices: choices:
- 768 - 768
- 1024 - 1024
- 1536 - 1536
- 2048 - 2048
ssl-max-version: ssl_max_version:
description: description:
- Highest SSL/TLS version to negotiate. - Highest SSL/TLS version to negotiate.
type: str
choices: choices:
- tls-1.0 - tls-1.0
- tls-1.1 - tls-1.1
- tls-1.2 - tls-1.2
ssl-min-version: ssl_min_version:
description: description:
- Lowest SSL/TLS version to negotiate. - Lowest SSL/TLS version to negotiate.
type: str
choices: choices:
- tls-1.0 - tls-1.0
- tls-1.1 - tls-1.1
- tls-1.2 - tls-1.2
ssl-mode: ssl_mode:
description: description:
- SSL/TLS mode for encryption and decryption of traffic. - SSL/TLS mode for encryption and decryption of traffic.
type: str
choices: choices:
- half - half
- full - full
ssl-send-empty-frags: ssl_send_empty_frags:
description: description:
- Enable/disable sending empty fragments to avoid attack on CBC IV. - Enable/disable sending empty fragments to avoid attack on CBC IV.
type: str
choices: choices:
- enable - enable
- disable - disable
url-rewrite: url_rewrite:
description: description:
- Enable/disable rewriting the URL. - Enable/disable rewriting the URL.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -163,6 +187,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure SSL servers. - name: Configure SSL servers.
fortios_firewall_ssl_server: fortios_firewall_ssl_server:
@ -171,22 +196,22 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_ssl_server: firewall_ssl_server:
state: "present" add_header_x_forwarded_proto: "enable"
add-header-x-forwarded-proto: "enable"
ip: "<your_own_value>" ip: "<your_own_value>"
mapped-port: "5" mapped_port: "5"
name: "default_name_6" name: "default_name_6"
port: "7" port: "7"
ssl-algorithm: "high" ssl_algorithm: "high"
ssl-cert: "<your_own_value> (source vpn.certificate.local.name)" ssl_cert: "<your_own_value> (source vpn.certificate.local.name)"
ssl-client-renegotiation: "allow" ssl_client_renegotiation: "allow"
ssl-dh-bits: "768" ssl_dh_bits: "768"
ssl-max-version: "tls-1.0" ssl_max_version: "tls-1.0"
ssl-min-version: "tls-1.0" ssl_min_version: "tls-1.0"
ssl-mode: "half" ssl_mode: "half"
ssl-send-empty-frags: "enable" ssl_send_empty_frags: "enable"
url-rewrite: "enable" url_rewrite: "enable"
''' '''
RETURN = ''' RETURN = '''
@ -249,14 +274,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -264,15 +291,15 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_ssl_server_data(json): def filter_firewall_ssl_server_data(json):
option_list = ['add-header-x-forwarded-proto', 'ip', 'mapped-port', option_list = ['add_header_x_forwarded_proto', 'ip', 'mapped_port',
'name', 'port', 'ssl-algorithm', 'name', 'port', 'ssl_algorithm',
'ssl-cert', 'ssl-client-renegotiation', 'ssl-dh-bits', 'ssl_cert', 'ssl_client_renegotiation', 'ssl_dh_bits',
'ssl-max-version', 'ssl-min-version', 'ssl-mode', 'ssl_max_version', 'ssl_min_version', 'ssl_mode',
'ssl-send-empty-frags', 'url-rewrite'] 'ssl_send_empty_frags', 'url_rewrite']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -282,71 +309,89 @@ def filter_firewall_ssl_server_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_ssl_server(data, fos): def firewall_ssl_server(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_ssl_server_data = data['firewall_ssl_server'] firewall_ssl_server_data = data['firewall_ssl_server']
filtered_data = filter_firewall_ssl_server_data(firewall_ssl_server_data) filtered_data = underscore_to_hyphen(filter_firewall_ssl_server_data(firewall_ssl_server_data))
if firewall_ssl_server_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'ssl-server', 'ssl-server',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_ssl_server_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'ssl-server', 'ssl-server',
mkey=filtered_data['name'], mkey=filtered_data['name'],
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall(data, fos): def fortios_firewall(data, fos):
login(data)
methodlist = ['firewall_ssl_server'] if data['firewall_ssl_server']:
for method in methodlist: resp = firewall_ssl_server(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_ssl_server": { "firewall_ssl_server": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "add_header_x_forwarded_proto": {"required": False, "type": "str",
"choices": ["present", "absent"]},
"add-header-x-forwarded-proto": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"ip": {"required": False, "type": "str"}, "ip": {"required": False, "type": "str"},
"mapped-port": {"required": False, "type": "int"}, "mapped_port": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"port": {"required": False, "type": "int"}, "port": {"required": False, "type": "int"},
"ssl-algorithm": {"required": False, "type": "str", "ssl_algorithm": {"required": False, "type": "str",
"choices": ["high", "medium", "low"]}, "choices": ["high", "medium", "low"]},
"ssl-cert": {"required": False, "type": "str"}, "ssl_cert": {"required": False, "type": "str"},
"ssl-client-renegotiation": {"required": False, "type": "str", "ssl_client_renegotiation": {"required": False, "type": "str",
"choices": ["allow", "deny", "secure"]}, "choices": ["allow", "deny", "secure"]},
"ssl-dh-bits": {"required": False, "type": "str", "ssl_dh_bits": {"required": False, "type": "str",
"choices": ["768", "1024", "1536", "choices": ["768", "1024", "1536",
"2048"]}, "2048"]},
"ssl-max-version": {"required": False, "type": "str", "ssl_max_version": {"required": False, "type": "str",
"choices": ["tls-1.0", "tls-1.1", "tls-1.2"]}, "choices": ["tls-1.0", "tls-1.1", "tls-1.2"]},
"ssl-min-version": {"required": False, "type": "str", "ssl_min_version": {"required": False, "type": "str",
"choices": ["tls-1.0", "tls-1.1", "tls-1.2"]}, "choices": ["tls-1.0", "tls-1.1", "tls-1.2"]},
"ssl-mode": {"required": False, "type": "str", "ssl_mode": {"required": False, "type": "str",
"choices": ["half", "full"]}, "choices": ["half", "full"]},
"ssl-send-empty-frags": {"required": False, "type": "str", "ssl_send_empty_frags": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"url-rewrite": {"required": False, "type": "str", "url_rewrite": {"required": False, "type": "str",
"choices": ["enable", "disable"]} "choices": ["enable", "disable"]}
} }
@ -355,15 +400,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>. # along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# the lib use python logging can get it if the following is set in your
# Ansible config.
__metaclass__ = type __metaclass__ = type
@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_firewall_ssl_setting module: fortios_firewall_ssl_setting
short_description: SSL proxy settings in Fortinet's FortiOS and FortiGate. short_description: SSL proxy settings in Fortinet's FortiOS and FortiGate.
description: description:
- This module is able to configure a FortiGate or FortiOS by - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
allowing the user to configure firewall_ssl feature and setting category. user to set and modify firewall_ssl feature and setting category.
Examples includes all options and need to be adjusted to datasources before usage. Examples include all parameters and values need to be adjusted to datasources before usage.
Tested with FOS v6.0.2 Tested with FOS v6.0.5
version_added: "2.8" version_added: "2.8"
author: author:
- Miguel Angel Munoz (@mamunozgonzalez) - Miguel Angel Munoz (@mamunozgonzalez)
@ -44,80 +41,99 @@ requirements:
- fortiosapi>=0.9.8 - fortiosapi>=0.9.8
options: options:
host: host:
description: description:
- FortiOS or FortiGate ip adress. - FortiOS or FortiGate IP address.
required: true type: str
required: false
username: username:
description: description:
- FortiOS or FortiGate username. - FortiOS or FortiGate username.
required: true type: str
required: false
password: password:
description: description:
- FortiOS or FortiGate password. - FortiOS or FortiGate password.
type: str
default: "" default: ""
vdom: vdom:
description: description:
- Virtual domain, among those defined previously. A vdom is a - Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and virtual instance of the FortiGate that can be configured and
used as a different unit. used as a different unit.
type: str
default: root default: root
https: https:
description: description:
- Indicates if the requests towards FortiGate must use HTTPS - Indicates if the requests towards FortiGate must use HTTPS protocol.
protocol type: bool
default: true
ssl_verify:
description:
- Ensures FortiGate certificate must be verified by a proper CA.
type: bool type: bool
default: true default: true
version_added: 2.9
firewall_ssl_setting: firewall_ssl_setting:
description: description:
- SSL proxy settings. - SSL proxy settings.
default: null default: null
type: dict
suboptions: suboptions:
abbreviate-handshake: abbreviate_handshake:
description: description:
- Enable/disable use of SSL abbreviated handshake. - Enable/disable use of SSL abbreviated handshake.
type: str
choices: choices:
- enable - enable
- disable - disable
cert-cache-capacity: cert_cache_capacity:
description: description:
- Maximum capacity of the host certificate cache (0 - 500, default = 200). - Maximum capacity of the host certificate cache (0 - 500).
cert-cache-timeout: type: int
cert_cache_timeout:
description: description:
- Time limit to keep certificate cache (1 - 120 min, default = 10). - Time limit to keep certificate cache (1 - 120 min).
kxp-queue-threshold: type: int
kxp_queue_threshold:
description: description:
- Maximum length of the CP KXP queue. When the queue becomes full, the proxy switches cipher functions to the main CPU (0 - 512, default = - Maximum length of the CP KXP queue. When the queue becomes full, the proxy switches cipher functions to the main CPU (0 - 512).
16). type: int
no-matching-cipher-action: no_matching_cipher_action:
description: description:
- Bypass or drop the connection when no matching cipher is found. - Bypass or drop the connection when no matching cipher is found.
type: str
choices: choices:
- bypass - bypass
- drop - drop
proxy-connect-timeout: proxy_connect_timeout:
description: description:
- Time limit to make an internal connection to the appropriate proxy process (1 - 60 sec, default = 30). - Time limit to make an internal connection to the appropriate proxy process (1 - 60 sec).
session-cache-capacity: type: int
session_cache_capacity:
description: description:
- Capacity of the SSL session cache (--Obsolete--) (1 - 1000, default = 500). - Capacity of the SSL session cache (--Obsolete--) (1 - 1000).
session-cache-timeout: type: int
session_cache_timeout:
description: description:
- Time limit to keep SSL session state (1 - 60 min, default = 20). - Time limit to keep SSL session state (1 - 60 min).
ssl-dh-bits: type: int
ssl_dh_bits:
description: description:
- Bit-size of Diffie-Hellman (DH) prime used in DHE-RSA negotiation (default = 2048). - Bit-size of Diffie-Hellman (DH) prime used in DHE-RSA negotiation.
type: str
choices: choices:
- 768 - 768
- 1024 - 1024
- 1536 - 1536
- 2048 - 2048
ssl-queue-threshold: ssl_queue_threshold:
description: description:
- Maximum length of the CP SSL queue. When the queue becomes full, the proxy switches cipher functions to the main CPU (0 - 512, default = - Maximum length of the CP SSL queue. When the queue becomes full, the proxy switches cipher functions to the main CPU (0 - 512).
32). type: int
ssl-send-empty-frags: ssl_send_empty_frags:
description: description:
- Enable/disable sending empty fragments to avoid attack on CBC IV (for SSL 3.0 and TLS 1.0 only). - Enable/disable sending empty fragments to avoid attack on CBC IV (for SSL 3.0 and TLS 1.0 only).
type: str
choices: choices:
- enable - enable
- disable - disable
@ -130,6 +146,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: SSL proxy settings. - name: SSL proxy settings.
fortios_firewall_ssl_setting: fortios_firewall_ssl_setting:
@ -139,17 +156,17 @@ EXAMPLES = '''
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
firewall_ssl_setting: firewall_ssl_setting:
abbreviate-handshake: "enable" abbreviate_handshake: "enable"
cert-cache-capacity: "4" cert_cache_capacity: "4"
cert-cache-timeout: "5" cert_cache_timeout: "5"
kxp-queue-threshold: "6" kxp_queue_threshold: "6"
no-matching-cipher-action: "bypass" no_matching_cipher_action: "bypass"
proxy-connect-timeout: "8" proxy_connect_timeout: "8"
session-cache-capacity: "9" session_cache_capacity: "9"
session-cache-timeout: "10" session_cache_timeout: "10"
ssl-dh-bits: "768" ssl_dh_bits: "768"
ssl-queue-threshold: "12" ssl_queue_threshold: "12"
ssl-send-empty-frags: "enable" ssl_send_empty_frags: "enable"
''' '''
RETURN = ''' RETURN = '''
@ -212,14 +229,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
fos = None from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data): def login(data, fos):
host = data['host'] host = data['host']
username = data['username'] username = data['username']
password = data['password'] password = data['password']
ssl_verify = data['ssl_verify']
fos.debug('on') fos.debug('on')
if 'https' in data and not data['https']: if 'https' in data and not data['https']:
@ -227,14 +246,14 @@ def login(data):
else: else:
fos.https('on') fos.https('on')
fos.login(host, username, password) fos.login(host, username, password, verify=ssl_verify)
def filter_firewall_ssl_setting_data(json): def filter_firewall_ssl_setting_data(json):
option_list = ['abbreviate-handshake', 'cert-cache-capacity', 'cert-cache-timeout', option_list = ['abbreviate_handshake', 'cert_cache_capacity', 'cert_cache_timeout',
'kxp-queue-threshold', 'no-matching-cipher-action', 'proxy-connect-timeout', 'kxp_queue_threshold', 'no_matching_cipher_action', 'proxy_connect_timeout',
'session-cache-capacity', 'session-cache-timeout', 'ssl-dh-bits', 'session_cache_capacity', 'session_cache_timeout', 'ssl_dh_bits',
'ssl-queue-threshold', 'ssl-send-empty-frags'] 'ssl_queue_threshold', 'ssl_send_empty_frags']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -244,54 +263,71 @@ def filter_firewall_ssl_setting_data(json):
return dictionary return dictionary
def underscore_to_hyphen(data):
if isinstance(data, list):
for elem in data:
elem = underscore_to_hyphen(elem)
elif isinstance(data, dict):
new_data = {}
for k, v in data.items():
new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
data = new_data
return data
def firewall_ssl_setting(data, fos): def firewall_ssl_setting(data, fos):
vdom = data['vdom'] vdom = data['vdom']
firewall_ssl_setting_data = data['firewall_ssl_setting'] firewall_ssl_setting_data = data['firewall_ssl_setting']
filtered_data = filter_firewall_ssl_setting_data(firewall_ssl_setting_data) filtered_data = underscore_to_hyphen(filter_firewall_ssl_setting_data(firewall_ssl_setting_data))
return fos.set('firewall.ssl', return fos.set('firewall.ssl',
'setting', 'setting',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
def is_successful_status(status):
return status['status'] == "success" or \
status['http_method'] == "DELETE" and status['http_status'] == 404
def fortios_firewall_ssl(data, fos): def fortios_firewall_ssl(data, fos):
login(data)
methodlist = ['firewall_ssl_setting'] if data['firewall_ssl_setting']:
for method in methodlist: resp = firewall_ssl_setting(data, fos)
if data[method]:
resp = eval(method)(data, fos)
break
fos.logout() return not is_successful_status(resp), \
return not resp['status'] == "success", resp['status'] == "success", resp resp['status'] == "success", \
resp
def main(): def main():
fields = { fields = {
"host": {"required": True, "type": "str"}, "host": {"required": False, "type": "str"},
"username": {"required": True, "type": "str"}, "username": {"required": False, "type": "str"},
"password": {"required": False, "type": "str", "no_log": True}, "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"}, "vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"firewall_ssl_setting": { "firewall_ssl_setting": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"abbreviate-handshake": {"required": False, "type": "str", "abbreviate_handshake": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"cert-cache-capacity": {"required": False, "type": "int"}, "cert_cache_capacity": {"required": False, "type": "int"},
"cert-cache-timeout": {"required": False, "type": "int"}, "cert_cache_timeout": {"required": False, "type": "int"},
"kxp-queue-threshold": {"required": False, "type": "int"}, "kxp_queue_threshold": {"required": False, "type": "int"},
"no-matching-cipher-action": {"required": False, "type": "str", "no_matching_cipher_action": {"required": False, "type": "str",
"choices": ["bypass", "drop"]}, "choices": ["bypass", "drop"]},
"proxy-connect-timeout": {"required": False, "type": "int"}, "proxy_connect_timeout": {"required": False, "type": "int"},
"session-cache-capacity": {"required": False, "type": "int"}, "session_cache_capacity": {"required": False, "type": "int"},
"session-cache-timeout": {"required": False, "type": "int"}, "session_cache_timeout": {"required": False, "type": "int"},
"ssl-dh-bits": {"required": False, "type": "str", "ssl_dh_bits": {"required": False, "type": "str",
"choices": ["768", "1024", "1536", "choices": ["768", "1024", "1536",
"2048"]}, "2048"]},
"ssl-queue-threshold": {"required": False, "type": "int"}, "ssl_queue_threshold": {"required": False, "type": "int"},
"ssl-send-empty-frags": {"required": False, "type": "str", "ssl_send_empty_frags": {"required": False, "type": "str",
"choices": ["enable", "disable"]} "choices": ["enable", "disable"]}
} }
@ -300,15 +336,31 @@ def main():
module = AnsibleModule(argument_spec=fields, module = AnsibleModule(argument_spec=fields,
supports_check_mode=False) supports_check_mode=False)
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
global fos # legacy_mode refers to using fortiosapi instead of HTTPAPI
fos = FortiOSAPI() legacy_mode = 'host' in module.params and module.params['host'] is not None and \
'username' in module.params and module.params['username'] is not None and \
'password' in module.params and module.params['password'] is not None
if not legacy_mode:
if module._socket_path:
connection = Connection(module._socket_path)
fos = FortiOSHandler(connection)
is_error, has_changed, result = fortios_firewall_ssl(module.params, fos)
else:
module.fail_json(**FAIL_SOCKET_MSG)
else:
try:
from fortiosapi import FortiOSAPI
except ImportError:
module.fail_json(msg="fortiosapi module is required")
fos = FortiOSAPI()
is_error, has_changed, result = fortios_firewall_ssl(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_ssl(module.params, fos)
fos.logout()
if not is_error: if not is_error:
module.exit_json(changed=has_changed, meta=result) module.exit_json(changed=has_changed, meta=result)

@ -3694,41 +3694,7 @@ lib/ansible/modules/network/fortios/fortios_config.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_DoS_policy.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_firewall_DoS_policy.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_DoS_policy6.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_firewall_DoS_policy6.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_policy.py validate-modules:E326 lib/ansible/modules/network/fortios/fortios_firewall_policy.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_firewall_proxy_address.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_proxy_address.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_proxy_addrgrp.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_proxy_policy.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_proxy_policy.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_schedule_group.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_schedule_onetime.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_schedule_onetime.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_schedule_recurring.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_service_category.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_service_custom.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_service_custom.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_service_group.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_shaper_per_ip_shaper.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_shaper_per_ip_shaper.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_shaper_traffic_shaper.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_shaper_traffic_shaper.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_shaping_policy.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_shaping_policy.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_shaping_profile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_shaping_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_sniffer.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_firewall_sniffer.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_sniffer.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssh_host_key.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssh_host_key.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssh_local_ca.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssh_local_ca.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssh_local_key.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssh_local_key.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssh_setting.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssh_setting.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssl_server.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssl_server.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssl_setting.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssl_setting.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ssl_ssh_profile.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_firewall_ssl_ssh_profile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_ssl_ssh_profile.py validate-modules:E337 lib/ansible/modules/network/fortios/fortios_firewall_ssl_ssh_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_ttl_policy.py validate-modules:E337 lib/ansible/modules/network/fortios/fortios_firewall_ttl_policy.py validate-modules:E337

@ -0,0 +1,349 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_proxy_address
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_proxy_address.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_proxy_address_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_address': {
'case_sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header_name': 'test_value_7',
'host': 'myhostname8',
'host_regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_address.fortios_firewall(input_data, fos_instance)
expected_data = {
'case-sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header-name': 'test_value_7',
'host': 'myhostname8',
'host-regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-address', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_proxy_address_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_address': {
'case_sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header_name': 'test_value_7',
'host': 'myhostname8',
'host_regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_address.fortios_firewall(input_data, fos_instance)
expected_data = {
'case-sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header-name': 'test_value_7',
'host': 'myhostname8',
'host-regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-address', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_proxy_address_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_proxy_address': {
'case_sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header_name': 'test_value_7',
'host': 'myhostname8',
'host_regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_address.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'proxy-address', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_proxy_address_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_proxy_address': {
'case_sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header_name': 'test_value_7',
'host': 'myhostname8',
'host_regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_address.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'proxy-address', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_proxy_address_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_address': {
'case_sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header_name': 'test_value_7',
'host': 'myhostname8',
'host_regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_address.fortios_firewall(input_data, fos_instance)
expected_data = {
'case-sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header-name': 'test_value_7',
'host': 'myhostname8',
'host-regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-address', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_proxy_address_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_address': {
'random_attribute_not_valid': 'tag',
'case_sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header_name': 'test_value_7',
'host': 'myhostname8',
'host_regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_address.fortios_firewall(input_data, fos_instance)
expected_data = {
'case-sensitivity': 'disable',
'color': '4',
'comment': 'Optional comments.',
'header': 'test_value_6',
'header-name': 'test_value_7',
'host': 'myhostname8',
'host-regex': 'myhostname9',
'method': 'get',
'name': 'default_name_11',
'path': 'test_value_12',
'query': 'test_value_13',
'referrer': 'enable',
'type': 'host-regex',
'ua': 'chrome',
'uuid': 'test_value_17',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-address', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,249 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_proxy_addrgrp
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_proxy_addrgrp.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_proxy_addrgrp_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_addrgrp': {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_addrgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-addrgrp', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_proxy_addrgrp_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_addrgrp': {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_addrgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-addrgrp', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_proxy_addrgrp_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_proxy_addrgrp': {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_addrgrp.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'proxy-addrgrp', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_proxy_addrgrp_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_proxy_addrgrp': {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_addrgrp.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'proxy-addrgrp', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_proxy_addrgrp_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_addrgrp': {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_addrgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-addrgrp', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_proxy_addrgrp_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_addrgrp': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_addrgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Optional comments.',
'name': 'default_name_5',
'type': 'src',
'uuid': 'test_value_7',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall', 'proxy-addrgrp', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,599 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_proxy_policy
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_proxy_policy.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_proxy_policy_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_policy': {
'action': 'accept',
'application_list': 'test_value_4',
'av_profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp_sensor': 'test_value_8',
'dstaddr_negate': 'enable',
'global_label': 'test_value_10',
'http_tunnel_auth': 'enable',
'icap_profile': 'test_value_12',
'internet_service': 'enable',
'internet_service_negate': 'enable',
'ips_sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic_start': 'enable',
'policyid': '19',
'profile_group': 'test_value_20',
'profile_protocol_options': 'test_value_21',
'profile_type': 'single',
'proxy': 'explicit-web',
'redirect_url': 'test_value_24',
'replacemsg_override_group': 'test_value_25',
'scan_botnet_connections': 'disable',
'schedule': 'test_value_27',
'service_negate': 'enable',
'session_ttl': '29',
'spamfilter_profile': 'test_value_30',
'srcaddr_negate': 'enable',
'ssh_filter_profile': 'test_value_32',
'ssl_ssh_profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm_status': 'enable',
'uuid': 'test_value_37',
'waf_profile': 'test_value_38',
'webcache': 'enable',
'webcache_https': 'disable',
'webfilter_profile': 'test_value_41',
'webproxy_forward_server': 'test_value_42',
'webproxy_profile': 'test_value_43'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'application-list': 'test_value_4',
'av-profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp-sensor': 'test_value_8',
'dstaddr-negate': 'enable',
'global-label': 'test_value_10',
'http-tunnel-auth': 'enable',
'icap-profile': 'test_value_12',
'internet-service': 'enable',
'internet-service-negate': 'enable',
'ips-sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic-start': 'enable',
'policyid': '19',
'profile-group': 'test_value_20',
'profile-protocol-options': 'test_value_21',
'profile-type': 'single',
'proxy': 'explicit-web',
'redirect-url': 'test_value_24',
'replacemsg-override-group': 'test_value_25',
'scan-botnet-connections': 'disable',
'schedule': 'test_value_27',
'service-negate': 'enable',
'session-ttl': '29',
'spamfilter-profile': 'test_value_30',
'srcaddr-negate': 'enable',
'ssh-filter-profile': 'test_value_32',
'ssl-ssh-profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm-status': 'enable',
'uuid': 'test_value_37',
'waf-profile': 'test_value_38',
'webcache': 'enable',
'webcache-https': 'disable',
'webfilter-profile': 'test_value_41',
'webproxy-forward-server': 'test_value_42',
'webproxy-profile': 'test_value_43'
}
set_method_mock.assert_called_with('firewall', 'proxy-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_proxy_policy_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_policy': {
'action': 'accept',
'application_list': 'test_value_4',
'av_profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp_sensor': 'test_value_8',
'dstaddr_negate': 'enable',
'global_label': 'test_value_10',
'http_tunnel_auth': 'enable',
'icap_profile': 'test_value_12',
'internet_service': 'enable',
'internet_service_negate': 'enable',
'ips_sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic_start': 'enable',
'policyid': '19',
'profile_group': 'test_value_20',
'profile_protocol_options': 'test_value_21',
'profile_type': 'single',
'proxy': 'explicit-web',
'redirect_url': 'test_value_24',
'replacemsg_override_group': 'test_value_25',
'scan_botnet_connections': 'disable',
'schedule': 'test_value_27',
'service_negate': 'enable',
'session_ttl': '29',
'spamfilter_profile': 'test_value_30',
'srcaddr_negate': 'enable',
'ssh_filter_profile': 'test_value_32',
'ssl_ssh_profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm_status': 'enable',
'uuid': 'test_value_37',
'waf_profile': 'test_value_38',
'webcache': 'enable',
'webcache_https': 'disable',
'webfilter_profile': 'test_value_41',
'webproxy_forward_server': 'test_value_42',
'webproxy_profile': 'test_value_43'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'application-list': 'test_value_4',
'av-profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp-sensor': 'test_value_8',
'dstaddr-negate': 'enable',
'global-label': 'test_value_10',
'http-tunnel-auth': 'enable',
'icap-profile': 'test_value_12',
'internet-service': 'enable',
'internet-service-negate': 'enable',
'ips-sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic-start': 'enable',
'policyid': '19',
'profile-group': 'test_value_20',
'profile-protocol-options': 'test_value_21',
'profile-type': 'single',
'proxy': 'explicit-web',
'redirect-url': 'test_value_24',
'replacemsg-override-group': 'test_value_25',
'scan-botnet-connections': 'disable',
'schedule': 'test_value_27',
'service-negate': 'enable',
'session-ttl': '29',
'spamfilter-profile': 'test_value_30',
'srcaddr-negate': 'enable',
'ssh-filter-profile': 'test_value_32',
'ssl-ssh-profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm-status': 'enable',
'uuid': 'test_value_37',
'waf-profile': 'test_value_38',
'webcache': 'enable',
'webcache-https': 'disable',
'webfilter-profile': 'test_value_41',
'webproxy-forward-server': 'test_value_42',
'webproxy-profile': 'test_value_43'
}
set_method_mock.assert_called_with('firewall', 'proxy-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_proxy_policy_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_proxy_policy': {
'action': 'accept',
'application_list': 'test_value_4',
'av_profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp_sensor': 'test_value_8',
'dstaddr_negate': 'enable',
'global_label': 'test_value_10',
'http_tunnel_auth': 'enable',
'icap_profile': 'test_value_12',
'internet_service': 'enable',
'internet_service_negate': 'enable',
'ips_sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic_start': 'enable',
'policyid': '19',
'profile_group': 'test_value_20',
'profile_protocol_options': 'test_value_21',
'profile_type': 'single',
'proxy': 'explicit-web',
'redirect_url': 'test_value_24',
'replacemsg_override_group': 'test_value_25',
'scan_botnet_connections': 'disable',
'schedule': 'test_value_27',
'service_negate': 'enable',
'session_ttl': '29',
'spamfilter_profile': 'test_value_30',
'srcaddr_negate': 'enable',
'ssh_filter_profile': 'test_value_32',
'ssl_ssh_profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm_status': 'enable',
'uuid': 'test_value_37',
'waf_profile': 'test_value_38',
'webcache': 'enable',
'webcache_https': 'disable',
'webfilter_profile': 'test_value_41',
'webproxy_forward_server': 'test_value_42',
'webproxy_profile': 'test_value_43'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_policy.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'proxy-policy', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_proxy_policy_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_proxy_policy': {
'action': 'accept',
'application_list': 'test_value_4',
'av_profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp_sensor': 'test_value_8',
'dstaddr_negate': 'enable',
'global_label': 'test_value_10',
'http_tunnel_auth': 'enable',
'icap_profile': 'test_value_12',
'internet_service': 'enable',
'internet_service_negate': 'enable',
'ips_sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic_start': 'enable',
'policyid': '19',
'profile_group': 'test_value_20',
'profile_protocol_options': 'test_value_21',
'profile_type': 'single',
'proxy': 'explicit-web',
'redirect_url': 'test_value_24',
'replacemsg_override_group': 'test_value_25',
'scan_botnet_connections': 'disable',
'schedule': 'test_value_27',
'service_negate': 'enable',
'session_ttl': '29',
'spamfilter_profile': 'test_value_30',
'srcaddr_negate': 'enable',
'ssh_filter_profile': 'test_value_32',
'ssl_ssh_profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm_status': 'enable',
'uuid': 'test_value_37',
'waf_profile': 'test_value_38',
'webcache': 'enable',
'webcache_https': 'disable',
'webfilter_profile': 'test_value_41',
'webproxy_forward_server': 'test_value_42',
'webproxy_profile': 'test_value_43'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_policy.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'proxy-policy', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_proxy_policy_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_policy': {
'action': 'accept',
'application_list': 'test_value_4',
'av_profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp_sensor': 'test_value_8',
'dstaddr_negate': 'enable',
'global_label': 'test_value_10',
'http_tunnel_auth': 'enable',
'icap_profile': 'test_value_12',
'internet_service': 'enable',
'internet_service_negate': 'enable',
'ips_sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic_start': 'enable',
'policyid': '19',
'profile_group': 'test_value_20',
'profile_protocol_options': 'test_value_21',
'profile_type': 'single',
'proxy': 'explicit-web',
'redirect_url': 'test_value_24',
'replacemsg_override_group': 'test_value_25',
'scan_botnet_connections': 'disable',
'schedule': 'test_value_27',
'service_negate': 'enable',
'session_ttl': '29',
'spamfilter_profile': 'test_value_30',
'srcaddr_negate': 'enable',
'ssh_filter_profile': 'test_value_32',
'ssl_ssh_profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm_status': 'enable',
'uuid': 'test_value_37',
'waf_profile': 'test_value_38',
'webcache': 'enable',
'webcache_https': 'disable',
'webfilter_profile': 'test_value_41',
'webproxy_forward_server': 'test_value_42',
'webproxy_profile': 'test_value_43'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'application-list': 'test_value_4',
'av-profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp-sensor': 'test_value_8',
'dstaddr-negate': 'enable',
'global-label': 'test_value_10',
'http-tunnel-auth': 'enable',
'icap-profile': 'test_value_12',
'internet-service': 'enable',
'internet-service-negate': 'enable',
'ips-sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic-start': 'enable',
'policyid': '19',
'profile-group': 'test_value_20',
'profile-protocol-options': 'test_value_21',
'profile-type': 'single',
'proxy': 'explicit-web',
'redirect-url': 'test_value_24',
'replacemsg-override-group': 'test_value_25',
'scan-botnet-connections': 'disable',
'schedule': 'test_value_27',
'service-negate': 'enable',
'session-ttl': '29',
'spamfilter-profile': 'test_value_30',
'srcaddr-negate': 'enable',
'ssh-filter-profile': 'test_value_32',
'ssl-ssh-profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm-status': 'enable',
'uuid': 'test_value_37',
'waf-profile': 'test_value_38',
'webcache': 'enable',
'webcache-https': 'disable',
'webfilter-profile': 'test_value_41',
'webproxy-forward-server': 'test_value_42',
'webproxy-profile': 'test_value_43'
}
set_method_mock.assert_called_with('firewall', 'proxy-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_proxy_policy_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_proxy_policy': {
'random_attribute_not_valid': 'tag',
'action': 'accept',
'application_list': 'test_value_4',
'av_profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp_sensor': 'test_value_8',
'dstaddr_negate': 'enable',
'global_label': 'test_value_10',
'http_tunnel_auth': 'enable',
'icap_profile': 'test_value_12',
'internet_service': 'enable',
'internet_service_negate': 'enable',
'ips_sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic_start': 'enable',
'policyid': '19',
'profile_group': 'test_value_20',
'profile_protocol_options': 'test_value_21',
'profile_type': 'single',
'proxy': 'explicit-web',
'redirect_url': 'test_value_24',
'replacemsg_override_group': 'test_value_25',
'scan_botnet_connections': 'disable',
'schedule': 'test_value_27',
'service_negate': 'enable',
'session_ttl': '29',
'spamfilter_profile': 'test_value_30',
'srcaddr_negate': 'enable',
'ssh_filter_profile': 'test_value_32',
'ssl_ssh_profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm_status': 'enable',
'uuid': 'test_value_37',
'waf_profile': 'test_value_38',
'webcache': 'enable',
'webcache_https': 'disable',
'webfilter_profile': 'test_value_41',
'webproxy_forward_server': 'test_value_42',
'webproxy_profile': 'test_value_43'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_proxy_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'application-list': 'test_value_4',
'av-profile': 'test_value_5',
'comments': 'test_value_6',
'disclaimer': 'disable',
'dlp-sensor': 'test_value_8',
'dstaddr-negate': 'enable',
'global-label': 'test_value_10',
'http-tunnel-auth': 'enable',
'icap-profile': 'test_value_12',
'internet-service': 'enable',
'internet-service-negate': 'enable',
'ips-sensor': 'test_value_15',
'label': 'test_value_16',
'logtraffic': 'all',
'logtraffic-start': 'enable',
'policyid': '19',
'profile-group': 'test_value_20',
'profile-protocol-options': 'test_value_21',
'profile-type': 'single',
'proxy': 'explicit-web',
'redirect-url': 'test_value_24',
'replacemsg-override-group': 'test_value_25',
'scan-botnet-connections': 'disable',
'schedule': 'test_value_27',
'service-negate': 'enable',
'session-ttl': '29',
'spamfilter-profile': 'test_value_30',
'srcaddr-negate': 'enable',
'ssh-filter-profile': 'test_value_32',
'ssl-ssh-profile': 'test_value_33',
'status': 'enable',
'transparent': 'enable',
'utm-status': 'enable',
'uuid': 'test_value_37',
'waf-profile': 'test_value_38',
'webcache': 'enable',
'webcache-https': 'disable',
'webfilter-profile': 'test_value_41',
'webproxy-forward-server': 'test_value_42',
'webproxy-profile': 'test_value_43'
}
set_method_mock.assert_called_with('firewall', 'proxy-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,209 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_schedule_group
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_schedule_group.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_schedule_group_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_group': {
'color': '3',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_group.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.schedule', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_schedule_group_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_group': {
'color': '3',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_group.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.schedule', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_schedule_group_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_schedule_group': {
'color': '3',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_group.fortios_firewall_schedule(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.schedule', 'group', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_schedule_group_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_schedule_group': {
'color': '3',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_group.fortios_firewall_schedule(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.schedule', 'group', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_schedule_group_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_group': {
'color': '3',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_group.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.schedule', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_schedule_group_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_group': {
'random_attribute_not_valid': 'tag',
'color': '3',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_group.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.schedule', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,239 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_schedule_onetime
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_schedule_onetime.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_schedule_onetime_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_onetime': {
'color': '3',
'end': 'test_value_4',
'expiration_days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_onetime.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'end': 'test_value_4',
'expiration-days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'onetime', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_schedule_onetime_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_onetime': {
'color': '3',
'end': 'test_value_4',
'expiration_days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_onetime.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'end': 'test_value_4',
'expiration-days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'onetime', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_schedule_onetime_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_schedule_onetime': {
'color': '3',
'end': 'test_value_4',
'expiration_days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_onetime.fortios_firewall_schedule(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.schedule', 'onetime', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_schedule_onetime_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_schedule_onetime': {
'color': '3',
'end': 'test_value_4',
'expiration_days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_onetime.fortios_firewall_schedule(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.schedule', 'onetime', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_schedule_onetime_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_onetime': {
'color': '3',
'end': 'test_value_4',
'expiration_days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_onetime.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'end': 'test_value_4',
'expiration-days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'onetime', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_schedule_onetime_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_onetime': {
'random_attribute_not_valid': 'tag',
'color': '3',
'end': 'test_value_4',
'expiration_days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_onetime.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'end': 'test_value_4',
'expiration-days': '5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'onetime', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,239 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_schedule_recurring
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_schedule_recurring.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_schedule_recurring_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_recurring': {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_recurring.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'recurring', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_schedule_recurring_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_recurring': {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_recurring.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'recurring', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_schedule_recurring_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_schedule_recurring': {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_recurring.fortios_firewall_schedule(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.schedule', 'recurring', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_schedule_recurring_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_schedule_recurring': {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_recurring.fortios_firewall_schedule(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.schedule', 'recurring', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_schedule_recurring_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_recurring': {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_recurring.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'recurring', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_schedule_recurring_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_schedule_recurring': {
'random_attribute_not_valid': 'tag',
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_schedule_recurring.fortios_firewall_schedule(input_data, fos_instance)
expected_data = {
'color': '3',
'day': 'sunday',
'end': 'test_value_5',
'name': 'default_name_6',
'start': 'test_value_7'
}
set_method_mock.assert_called_with('firewall.schedule', 'recurring', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,209 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_service_category
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_service_category.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_service_category_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_category': {
'comment': 'Comment.',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_category.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.service', 'category', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_service_category_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_category': {
'comment': 'Comment.',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_category.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.service', 'category', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_service_category_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_service_category': {
'comment': 'Comment.',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_category.fortios_firewall_service(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.service', 'category', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_service_category_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_service_category': {
'comment': 'Comment.',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_category.fortios_firewall_service(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.service', 'category', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_service_category_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_category': {
'comment': 'Comment.',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_category.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.service', 'category', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_service_category_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_category': {
'random_attribute_not_valid': 'tag',
'comment': 'Comment.',
'name': 'default_name_4'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_category.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'name': 'default_name_4'
}
set_method_mock.assert_called_with('firewall.service', 'category', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,409 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_service_custom
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_service_custom.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_service_custom_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_custom': {'app_service_type': 'disable',
'category': 'test_value_4',
'check_reset_range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol_number': '15',
'proxy': 'enable',
'sctp_portrange': 'test_value_17',
'session_ttl': '18',
'tcp_halfclose_timer': '19',
'tcp_halfopen_timer': '20',
'tcp_portrange': 'test_value_21',
'tcp_timewait_timer': '22',
'udp_idle_timer': '23',
'udp_portrange': 'test_value_24',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_custom.fortios_firewall_service(input_data, fos_instance)
expected_data = {'app-service-type': 'disable',
'category': 'test_value_4',
'check-reset-range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol-number': '15',
'proxy': 'enable',
'sctp-portrange': 'test_value_17',
'session-ttl': '18',
'tcp-halfclose-timer': '19',
'tcp-halfopen-timer': '20',
'tcp-portrange': 'test_value_21',
'tcp-timewait-timer': '22',
'udp-idle-timer': '23',
'udp-portrange': 'test_value_24',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'custom', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_service_custom_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_custom': {'app_service_type': 'disable',
'category': 'test_value_4',
'check_reset_range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol_number': '15',
'proxy': 'enable',
'sctp_portrange': 'test_value_17',
'session_ttl': '18',
'tcp_halfclose_timer': '19',
'tcp_halfopen_timer': '20',
'tcp_portrange': 'test_value_21',
'tcp_timewait_timer': '22',
'udp_idle_timer': '23',
'udp_portrange': 'test_value_24',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_custom.fortios_firewall_service(input_data, fos_instance)
expected_data = {'app-service-type': 'disable',
'category': 'test_value_4',
'check-reset-range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol-number': '15',
'proxy': 'enable',
'sctp-portrange': 'test_value_17',
'session-ttl': '18',
'tcp-halfclose-timer': '19',
'tcp-halfopen-timer': '20',
'tcp-portrange': 'test_value_21',
'tcp-timewait-timer': '22',
'udp-idle-timer': '23',
'udp-portrange': 'test_value_24',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'custom', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_service_custom_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_service_custom': {'app_service_type': 'disable',
'category': 'test_value_4',
'check_reset_range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol_number': '15',
'proxy': 'enable',
'sctp_portrange': 'test_value_17',
'session_ttl': '18',
'tcp_halfclose_timer': '19',
'tcp_halfopen_timer': '20',
'tcp_portrange': 'test_value_21',
'tcp_timewait_timer': '22',
'udp_idle_timer': '23',
'udp_portrange': 'test_value_24',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_custom.fortios_firewall_service(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.service', 'custom', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_service_custom_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_service_custom': {'app_service_type': 'disable',
'category': 'test_value_4',
'check_reset_range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol_number': '15',
'proxy': 'enable',
'sctp_portrange': 'test_value_17',
'session_ttl': '18',
'tcp_halfclose_timer': '19',
'tcp_halfopen_timer': '20',
'tcp_portrange': 'test_value_21',
'tcp_timewait_timer': '22',
'udp_idle_timer': '23',
'udp_portrange': 'test_value_24',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_custom.fortios_firewall_service(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.service', 'custom', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_service_custom_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_custom': {'app_service_type': 'disable',
'category': 'test_value_4',
'check_reset_range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol_number': '15',
'proxy': 'enable',
'sctp_portrange': 'test_value_17',
'session_ttl': '18',
'tcp_halfclose_timer': '19',
'tcp_halfopen_timer': '20',
'tcp_portrange': 'test_value_21',
'tcp_timewait_timer': '22',
'udp_idle_timer': '23',
'udp_portrange': 'test_value_24',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_custom.fortios_firewall_service(input_data, fos_instance)
expected_data = {'app-service-type': 'disable',
'category': 'test_value_4',
'check-reset-range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol-number': '15',
'proxy': 'enable',
'sctp-portrange': 'test_value_17',
'session-ttl': '18',
'tcp-halfclose-timer': '19',
'tcp-halfopen-timer': '20',
'tcp-portrange': 'test_value_21',
'tcp-timewait-timer': '22',
'udp-idle-timer': '23',
'udp-portrange': 'test_value_24',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'custom', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_service_custom_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_custom': {
'random_attribute_not_valid': 'tag', 'app_service_type': 'disable',
'category': 'test_value_4',
'check_reset_range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol_number': '15',
'proxy': 'enable',
'sctp_portrange': 'test_value_17',
'session_ttl': '18',
'tcp_halfclose_timer': '19',
'tcp_halfopen_timer': '20',
'tcp_portrange': 'test_value_21',
'tcp_timewait_timer': '22',
'udp_idle_timer': '23',
'udp_portrange': 'test_value_24',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_custom.fortios_firewall_service(input_data, fos_instance)
expected_data = {'app-service-type': 'disable',
'category': 'test_value_4',
'check-reset-range': 'disable',
'color': '6',
'comment': 'Comment.',
'fqdn': 'test_value_8',
'helper': 'auto',
'icmpcode': '10',
'icmptype': '11',
'iprange': 'test_value_12',
'name': 'default_name_13',
'protocol': 'TCP/UDP/SCTP',
'protocol-number': '15',
'proxy': 'enable',
'sctp-portrange': 'test_value_17',
'session-ttl': '18',
'tcp-halfclose-timer': '19',
'tcp-halfopen-timer': '20',
'tcp-portrange': 'test_value_21',
'tcp-timewait-timer': '22',
'udp-idle-timer': '23',
'udp-portrange': 'test_value_24',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'custom', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,229 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_service_group
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_service_group.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_service_group_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_group.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_service_group_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_group.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_service_group_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_service_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_group.fortios_firewall_service(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.service', 'group', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_service_group_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_service_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_group.fortios_firewall_service(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.service', 'group', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_service_group_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_group.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_service_group_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_service_group': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_service_group.fortios_firewall_service(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'proxy': 'enable'
}
set_method_mock.assert_called_with('firewall.service', 'group', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,269 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_shaper_per_ip_shaper
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_shaper_per_ip_shaper.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_shaper_per_ip_shaper_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_per_ip_shaper': {
'bandwidth_unit': 'kbps',
'diffserv_forward': 'enable',
'diffserv_reverse': 'enable',
'diffservcode_forward': 'test_value_6',
'diffservcode_rev': 'test_value_7',
'max_bandwidth': '8',
'max_concurrent_session': '9',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_per_ip_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv-forward': 'enable',
'diffserv-reverse': 'enable',
'diffservcode-forward': 'test_value_6',
'diffservcode-rev': 'test_value_7',
'max-bandwidth': '8',
'max-concurrent-session': '9',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('firewall.shaper', 'per-ip-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaper_per_ip_shaper_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_per_ip_shaper': {
'bandwidth_unit': 'kbps',
'diffserv_forward': 'enable',
'diffserv_reverse': 'enable',
'diffservcode_forward': 'test_value_6',
'diffservcode_rev': 'test_value_7',
'max_bandwidth': '8',
'max_concurrent_session': '9',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_per_ip_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv-forward': 'enable',
'diffserv-reverse': 'enable',
'diffservcode-forward': 'test_value_6',
'diffservcode-rev': 'test_value_7',
'max-bandwidth': '8',
'max-concurrent-session': '9',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('firewall.shaper', 'per-ip-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaper_per_ip_shaper_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaper_per_ip_shaper': {
'bandwidth_unit': 'kbps',
'diffserv_forward': 'enable',
'diffserv_reverse': 'enable',
'diffservcode_forward': 'test_value_6',
'diffservcode_rev': 'test_value_7',
'max_bandwidth': '8',
'max_concurrent_session': '9',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_per_ip_shaper.fortios_firewall_shaper(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.shaper', 'per-ip-shaper', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaper_per_ip_shaper_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaper_per_ip_shaper': {
'bandwidth_unit': 'kbps',
'diffserv_forward': 'enable',
'diffserv_reverse': 'enable',
'diffservcode_forward': 'test_value_6',
'diffservcode_rev': 'test_value_7',
'max_bandwidth': '8',
'max_concurrent_session': '9',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_per_ip_shaper.fortios_firewall_shaper(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.shaper', 'per-ip-shaper', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaper_per_ip_shaper_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_per_ip_shaper': {
'bandwidth_unit': 'kbps',
'diffserv_forward': 'enable',
'diffserv_reverse': 'enable',
'diffservcode_forward': 'test_value_6',
'diffservcode_rev': 'test_value_7',
'max_bandwidth': '8',
'max_concurrent_session': '9',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_per_ip_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv-forward': 'enable',
'diffserv-reverse': 'enable',
'diffservcode-forward': 'test_value_6',
'diffservcode-rev': 'test_value_7',
'max-bandwidth': '8',
'max-concurrent-session': '9',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('firewall.shaper', 'per-ip-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_shaper_per_ip_shaper_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_per_ip_shaper': {
'random_attribute_not_valid': 'tag',
'bandwidth_unit': 'kbps',
'diffserv_forward': 'enable',
'diffserv_reverse': 'enable',
'diffservcode_forward': 'test_value_6',
'diffservcode_rev': 'test_value_7',
'max_bandwidth': '8',
'max_concurrent_session': '9',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_per_ip_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv-forward': 'enable',
'diffserv-reverse': 'enable',
'diffservcode-forward': 'test_value_6',
'diffservcode-rev': 'test_value_7',
'max-bandwidth': '8',
'max-concurrent-session': '9',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('firewall.shaper', 'per-ip-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,269 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_shaper_traffic_shaper
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_shaper_traffic_shaper.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_shaper_traffic_shaper_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_traffic_shaper': {
'bandwidth_unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed_bandwidth': '6',
'maximum_bandwidth': '7',
'name': 'default_name_8',
'per_policy': 'disable',
'priority': 'low'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_traffic_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed-bandwidth': '6',
'maximum-bandwidth': '7',
'name': 'default_name_8',
'per-policy': 'disable',
'priority': 'low'
}
set_method_mock.assert_called_with('firewall.shaper', 'traffic-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaper_traffic_shaper_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_traffic_shaper': {
'bandwidth_unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed_bandwidth': '6',
'maximum_bandwidth': '7',
'name': 'default_name_8',
'per_policy': 'disable',
'priority': 'low'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_traffic_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed-bandwidth': '6',
'maximum-bandwidth': '7',
'name': 'default_name_8',
'per-policy': 'disable',
'priority': 'low'
}
set_method_mock.assert_called_with('firewall.shaper', 'traffic-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaper_traffic_shaper_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaper_traffic_shaper': {
'bandwidth_unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed_bandwidth': '6',
'maximum_bandwidth': '7',
'name': 'default_name_8',
'per_policy': 'disable',
'priority': 'low'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_traffic_shaper.fortios_firewall_shaper(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.shaper', 'traffic-shaper', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaper_traffic_shaper_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaper_traffic_shaper': {
'bandwidth_unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed_bandwidth': '6',
'maximum_bandwidth': '7',
'name': 'default_name_8',
'per_policy': 'disable',
'priority': 'low'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_traffic_shaper.fortios_firewall_shaper(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.shaper', 'traffic-shaper', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaper_traffic_shaper_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_traffic_shaper': {
'bandwidth_unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed_bandwidth': '6',
'maximum_bandwidth': '7',
'name': 'default_name_8',
'per_policy': 'disable',
'priority': 'low'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_traffic_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed-bandwidth': '6',
'maximum-bandwidth': '7',
'name': 'default_name_8',
'per-policy': 'disable',
'priority': 'low'
}
set_method_mock.assert_called_with('firewall.shaper', 'traffic-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_shaper_traffic_shaper_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaper_traffic_shaper': {
'random_attribute_not_valid': 'tag',
'bandwidth_unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed_bandwidth': '6',
'maximum_bandwidth': '7',
'name': 'default_name_8',
'per_policy': 'disable',
'priority': 'low'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaper_traffic_shaper.fortios_firewall_shaper(input_data, fos_instance)
expected_data = {
'bandwidth-unit': 'kbps',
'diffserv': 'enable',
'diffservcode': 'test_value_5',
'guaranteed-bandwidth': '6',
'maximum-bandwidth': '7',
'name': 'default_name_8',
'per-policy': 'disable',
'priority': 'low'
}
set_method_mock.assert_called_with('firewall.shaper', 'traffic-shaper', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,299 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_shaping_policy
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_shaping_policy.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_shaping_policy_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_policy': {'class_id': '3',
'comment': 'Comments.',
'id': '5',
'internet_service': 'enable',
'internet_service_src': 'enable',
'ip_version': '4',
'per_ip_shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic_shaper': 'test_value_12',
'traffic_shaper_reverse': 'test_value_13',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_policy.fortios_firewall(input_data, fos_instance)
expected_data = {'class-id': '3',
'comment': 'Comments.',
'id': '5',
'internet-service': 'enable',
'internet-service-src': 'enable',
'ip-version': '4',
'per-ip-shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic-shaper': 'test_value_12',
'traffic-shaper-reverse': 'test_value_13',
}
set_method_mock.assert_called_with('firewall', 'shaping-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaping_policy_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_policy': {'class_id': '3',
'comment': 'Comments.',
'id': '5',
'internet_service': 'enable',
'internet_service_src': 'enable',
'ip_version': '4',
'per_ip_shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic_shaper': 'test_value_12',
'traffic_shaper_reverse': 'test_value_13',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_policy.fortios_firewall(input_data, fos_instance)
expected_data = {'class-id': '3',
'comment': 'Comments.',
'id': '5',
'internet-service': 'enable',
'internet-service-src': 'enable',
'ip-version': '4',
'per-ip-shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic-shaper': 'test_value_12',
'traffic-shaper-reverse': 'test_value_13',
}
set_method_mock.assert_called_with('firewall', 'shaping-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaping_policy_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaping_policy': {'class_id': '3',
'comment': 'Comments.',
'id': '5',
'internet_service': 'enable',
'internet_service_src': 'enable',
'ip_version': '4',
'per_ip_shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic_shaper': 'test_value_12',
'traffic_shaper_reverse': 'test_value_13',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_policy.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'shaping-policy', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaping_policy_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaping_policy': {'class_id': '3',
'comment': 'Comments.',
'id': '5',
'internet_service': 'enable',
'internet_service_src': 'enable',
'ip_version': '4',
'per_ip_shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic_shaper': 'test_value_12',
'traffic_shaper_reverse': 'test_value_13',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_policy.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'shaping-policy', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaping_policy_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_policy': {'class_id': '3',
'comment': 'Comments.',
'id': '5',
'internet_service': 'enable',
'internet_service_src': 'enable',
'ip_version': '4',
'per_ip_shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic_shaper': 'test_value_12',
'traffic_shaper_reverse': 'test_value_13',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_policy.fortios_firewall(input_data, fos_instance)
expected_data = {'class-id': '3',
'comment': 'Comments.',
'id': '5',
'internet-service': 'enable',
'internet-service-src': 'enable',
'ip-version': '4',
'per-ip-shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic-shaper': 'test_value_12',
'traffic-shaper-reverse': 'test_value_13',
}
set_method_mock.assert_called_with('firewall', 'shaping-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_shaping_policy_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_policy': {
'random_attribute_not_valid': 'tag', 'class_id': '3',
'comment': 'Comments.',
'id': '5',
'internet_service': 'enable',
'internet_service_src': 'enable',
'ip_version': '4',
'per_ip_shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic_shaper': 'test_value_12',
'traffic_shaper_reverse': 'test_value_13',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_policy.fortios_firewall(input_data, fos_instance)
expected_data = {'class-id': '3',
'comment': 'Comments.',
'id': '5',
'internet-service': 'enable',
'internet-service-src': 'enable',
'ip-version': '4',
'per-ip-shaper': 'test_value_9',
'schedule': 'test_value_10',
'status': 'enable',
'traffic-shaper': 'test_value_12',
'traffic-shaper-reverse': 'test_value_13',
}
set_method_mock.assert_called_with('firewall', 'shaping-policy', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,229 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_shaping_profile
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_shaping_profile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_shaping_profile_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_profile': {
'comment': 'Comment.',
'default_class_id': '4',
'profile_name': 'test_value_5',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'default-class-id': '4',
'profile-name': 'test_value_5',
}
set_method_mock.assert_called_with('firewall', 'shaping-profile', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaping_profile_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_profile': {
'comment': 'Comment.',
'default_class_id': '4',
'profile_name': 'test_value_5',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'default-class-id': '4',
'profile-name': 'test_value_5',
}
set_method_mock.assert_called_with('firewall', 'shaping-profile', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaping_profile_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaping_profile': {
'comment': 'Comment.',
'default_class_id': '4',
'profile_name': 'test_value_5',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_profile.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'shaping-profile', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_shaping_profile_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_shaping_profile': {
'comment': 'Comment.',
'default_class_id': '4',
'profile_name': 'test_value_5',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_profile.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'shaping-profile', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_shaping_profile_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_profile': {
'comment': 'Comment.',
'default_class_id': '4',
'profile_name': 'test_value_5',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'default-class-id': '4',
'profile-name': 'test_value_5',
}
set_method_mock.assert_called_with('firewall', 'shaping-profile', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_shaping_profile_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_shaping_profile': {
'random_attribute_not_valid': 'tag',
'comment': 'Comment.',
'default_class_id': '4',
'profile_name': 'test_value_5',
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_shaping_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'default-class-id': '4',
'profile-name': 'test_value_5',
}
set_method_mock.assert_called_with('firewall', 'shaping-profile', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,439 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_sniffer
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_sniffer.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_sniffer_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_sniffer': {'application_list': 'test_value_3',
'application_list_status': 'enable',
'av_profile': 'test_value_5',
'av_profile_status': 'enable',
'dlp_sensor': 'test_value_7',
'dlp_sensor_status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips_dos_status': 'enable',
'ips_sensor': 'test_value_14',
'ips_sensor_status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max_packet_count': '18',
'non_ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan_botnet_connections': 'disable',
'spamfilter_profile': 'test_value_23',
'spamfilter_profile_status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter_profile': 'test_value_27',
'webfilter_profile_status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_sniffer.fortios_firewall(input_data, fos_instance)
expected_data = {'application-list': 'test_value_3',
'application-list-status': 'enable',
'av-profile': 'test_value_5',
'av-profile-status': 'enable',
'dlp-sensor': 'test_value_7',
'dlp-sensor-status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips-dos-status': 'enable',
'ips-sensor': 'test_value_14',
'ips-sensor-status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max-packet-count': '18',
'non-ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan-botnet-connections': 'disable',
'spamfilter-profile': 'test_value_23',
'spamfilter-profile-status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter-profile': 'test_value_27',
'webfilter-profile-status': 'enable'
}
set_method_mock.assert_called_with('firewall', 'sniffer', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_sniffer_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_sniffer': {'application_list': 'test_value_3',
'application_list_status': 'enable',
'av_profile': 'test_value_5',
'av_profile_status': 'enable',
'dlp_sensor': 'test_value_7',
'dlp_sensor_status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips_dos_status': 'enable',
'ips_sensor': 'test_value_14',
'ips_sensor_status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max_packet_count': '18',
'non_ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan_botnet_connections': 'disable',
'spamfilter_profile': 'test_value_23',
'spamfilter_profile_status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter_profile': 'test_value_27',
'webfilter_profile_status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_sniffer.fortios_firewall(input_data, fos_instance)
expected_data = {'application-list': 'test_value_3',
'application-list-status': 'enable',
'av-profile': 'test_value_5',
'av-profile-status': 'enable',
'dlp-sensor': 'test_value_7',
'dlp-sensor-status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips-dos-status': 'enable',
'ips-sensor': 'test_value_14',
'ips-sensor-status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max-packet-count': '18',
'non-ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan-botnet-connections': 'disable',
'spamfilter-profile': 'test_value_23',
'spamfilter-profile-status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter-profile': 'test_value_27',
'webfilter-profile-status': 'enable'
}
set_method_mock.assert_called_with('firewall', 'sniffer', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_sniffer_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_sniffer': {'application_list': 'test_value_3',
'application_list_status': 'enable',
'av_profile': 'test_value_5',
'av_profile_status': 'enable',
'dlp_sensor': 'test_value_7',
'dlp_sensor_status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips_dos_status': 'enable',
'ips_sensor': 'test_value_14',
'ips_sensor_status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max_packet_count': '18',
'non_ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan_botnet_connections': 'disable',
'spamfilter_profile': 'test_value_23',
'spamfilter_profile_status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter_profile': 'test_value_27',
'webfilter_profile_status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_sniffer.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'sniffer', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_sniffer_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_sniffer': {'application_list': 'test_value_3',
'application_list_status': 'enable',
'av_profile': 'test_value_5',
'av_profile_status': 'enable',
'dlp_sensor': 'test_value_7',
'dlp_sensor_status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips_dos_status': 'enable',
'ips_sensor': 'test_value_14',
'ips_sensor_status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max_packet_count': '18',
'non_ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan_botnet_connections': 'disable',
'spamfilter_profile': 'test_value_23',
'spamfilter_profile_status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter_profile': 'test_value_27',
'webfilter_profile_status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_sniffer.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'sniffer', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_sniffer_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_sniffer': {'application_list': 'test_value_3',
'application_list_status': 'enable',
'av_profile': 'test_value_5',
'av_profile_status': 'enable',
'dlp_sensor': 'test_value_7',
'dlp_sensor_status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips_dos_status': 'enable',
'ips_sensor': 'test_value_14',
'ips_sensor_status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max_packet_count': '18',
'non_ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan_botnet_connections': 'disable',
'spamfilter_profile': 'test_value_23',
'spamfilter_profile_status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter_profile': 'test_value_27',
'webfilter_profile_status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_sniffer.fortios_firewall(input_data, fos_instance)
expected_data = {'application-list': 'test_value_3',
'application-list-status': 'enable',
'av-profile': 'test_value_5',
'av-profile-status': 'enable',
'dlp-sensor': 'test_value_7',
'dlp-sensor-status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips-dos-status': 'enable',
'ips-sensor': 'test_value_14',
'ips-sensor-status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max-packet-count': '18',
'non-ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan-botnet-connections': 'disable',
'spamfilter-profile': 'test_value_23',
'spamfilter-profile-status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter-profile': 'test_value_27',
'webfilter-profile-status': 'enable'
}
set_method_mock.assert_called_with('firewall', 'sniffer', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_sniffer_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_sniffer': {
'random_attribute_not_valid': 'tag', 'application_list': 'test_value_3',
'application_list_status': 'enable',
'av_profile': 'test_value_5',
'av_profile_status': 'enable',
'dlp_sensor': 'test_value_7',
'dlp_sensor_status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips_dos_status': 'enable',
'ips_sensor': 'test_value_14',
'ips_sensor_status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max_packet_count': '18',
'non_ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan_botnet_connections': 'disable',
'spamfilter_profile': 'test_value_23',
'spamfilter_profile_status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter_profile': 'test_value_27',
'webfilter_profile_status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_sniffer.fortios_firewall(input_data, fos_instance)
expected_data = {'application-list': 'test_value_3',
'application-list-status': 'enable',
'av-profile': 'test_value_5',
'av-profile-status': 'enable',
'dlp-sensor': 'test_value_7',
'dlp-sensor-status': 'enable',
'dsri': 'enable',
'host': 'myhostname10',
'id': '11',
'interface': 'test_value_12',
'ips-dos-status': 'enable',
'ips-sensor': 'test_value_14',
'ips-sensor-status': 'enable',
'ipv6': 'enable',
'logtraffic': 'all',
'max-packet-count': '18',
'non-ip': 'enable',
'port': 'test_value_20',
'protocol': 'test_value_21',
'scan-botnet-connections': 'disable',
'spamfilter-profile': 'test_value_23',
'spamfilter-profile-status': 'enable',
'status': 'enable',
'vlan': 'test_value_26',
'webfilter-profile': 'test_value_27',
'webfilter-profile-status': 'enable'
}
set_method_mock.assert_called_with('firewall', 'sniffer', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,269 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_ssh_host_key
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_ssh_host_key.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssh_host_key_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_host_key': {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public_key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_host_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public-key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
}
set_method_mock.assert_called_with('firewall.ssh', 'host-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_host_key_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_host_key': {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public_key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_host_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public-key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
}
set_method_mock.assert_called_with('firewall.ssh', 'host-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_host_key_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssh_host_key': {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public_key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_host_key.fortios_firewall_ssh(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.ssh', 'host-key', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_host_key_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssh_host_key': {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public_key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_host_key.fortios_firewall_ssh(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.ssh', 'host-key', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_host_key_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_host_key': {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public_key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_host_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public-key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
}
set_method_mock.assert_called_with('firewall.ssh', 'host-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_ssh_host_key_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_host_key': {
'random_attribute_not_valid': 'tag',
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public_key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_host_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'hostname': 'myhostname3',
'ip': 'test_value_4',
'name': 'default_name_5',
'nid': '256',
'port': '7',
'public-key': 'test_value_8',
'status': 'trusted',
'type': 'RSA'
}
set_method_mock.assert_called_with('firewall.ssh', 'host-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,239 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_ssh_local_ca
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_ssh_local_ca.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssh_local_ca_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_ca': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_ca.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-ca', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_local_ca_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_ca': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_ca.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-ca', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_local_ca_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssh_local_ca': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_ca.fortios_firewall_ssh(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.ssh', 'local-ca', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_local_ca_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssh_local_ca': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_ca.fortios_firewall_ssh(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.ssh', 'local-ca', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_local_ca_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_ca': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_ca.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-ca', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_ssh_local_ca_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_ca': {
'random_attribute_not_valid': 'tag',
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_ca.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-ca', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,239 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_ssh_local_key
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_ssh_local_key.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssh_local_key_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_key': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_local_key_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_key': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_local_key_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssh_local_key': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_key.fortios_firewall_ssh(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.ssh', 'local-key', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_local_key_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssh_local_key': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_key.fortios_firewall_ssh(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.ssh', 'local-key', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_local_key_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_key': {
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_ssh_local_key_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_local_key': {
'random_attribute_not_valid': 'tag',
'name': 'default_name_3',
'password': 'test_value_4',
'private_key': 'test_value_5',
'public_key': 'test_value_6',
'source': 'built-in'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_local_key.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'password': 'test_value_4',
'private-key': 'test_value_5',
'public-key': 'test_value_6',
'source': 'built-in'
}
set_method_mock.assert_called_with('firewall.ssh', 'local-key', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,215 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_ssh_setting
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_ssh_setting.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssh_setting_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_setting': {
'caname': 'test_value_3',
'host_trusted_checking': 'enable',
'hostkey_dsa1024': 'myhostname5',
'hostkey_ecdsa256': 'myhostname6',
'hostkey_ecdsa384': 'myhostname7',
'hostkey_ecdsa521': 'myhostname8',
'hostkey_ed25519': 'myhostname9',
'hostkey_rsa2048': 'myhostname10',
'untrusted_caname': 'test_value_11'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_setting.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'host-trusted-checking': 'enable',
'hostkey-dsa1024': 'myhostname5',
'hostkey-ecdsa256': 'myhostname6',
'hostkey-ecdsa384': 'myhostname7',
'hostkey-ecdsa521': 'myhostname8',
'hostkey-ed25519': 'myhostname9',
'hostkey-rsa2048': 'myhostname10',
'untrusted-caname': 'test_value_11'
}
set_method_mock.assert_called_with('firewall.ssh', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssh_setting_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_setting': {
'caname': 'test_value_3',
'host_trusted_checking': 'enable',
'hostkey_dsa1024': 'myhostname5',
'hostkey_ecdsa256': 'myhostname6',
'hostkey_ecdsa384': 'myhostname7',
'hostkey_ecdsa521': 'myhostname8',
'hostkey_ed25519': 'myhostname9',
'hostkey_rsa2048': 'myhostname10',
'untrusted_caname': 'test_value_11'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_setting.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'host-trusted-checking': 'enable',
'hostkey-dsa1024': 'myhostname5',
'hostkey-ecdsa256': 'myhostname6',
'hostkey-ecdsa384': 'myhostname7',
'hostkey-ecdsa521': 'myhostname8',
'hostkey-ed25519': 'myhostname9',
'hostkey-rsa2048': 'myhostname10',
'untrusted-caname': 'test_value_11'
}
set_method_mock.assert_called_with('firewall.ssh', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssh_setting_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_setting': {
'caname': 'test_value_3',
'host_trusted_checking': 'enable',
'hostkey_dsa1024': 'myhostname5',
'hostkey_ecdsa256': 'myhostname6',
'hostkey_ecdsa384': 'myhostname7',
'hostkey_ecdsa521': 'myhostname8',
'hostkey_ed25519': 'myhostname9',
'hostkey_rsa2048': 'myhostname10',
'untrusted_caname': 'test_value_11'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_setting.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'host-trusted-checking': 'enable',
'hostkey-dsa1024': 'myhostname5',
'hostkey-ecdsa256': 'myhostname6',
'hostkey-ecdsa384': 'myhostname7',
'hostkey-ecdsa521': 'myhostname8',
'hostkey-ed25519': 'myhostname9',
'hostkey-rsa2048': 'myhostname10',
'untrusted-caname': 'test_value_11'
}
set_method_mock.assert_called_with('firewall.ssh', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_ssh_setting_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssh_setting': {
'random_attribute_not_valid': 'tag',
'caname': 'test_value_3',
'host_trusted_checking': 'enable',
'hostkey_dsa1024': 'myhostname5',
'hostkey_ecdsa256': 'myhostname6',
'hostkey_ecdsa384': 'myhostname7',
'hostkey_ecdsa521': 'myhostname8',
'hostkey_ed25519': 'myhostname9',
'hostkey_rsa2048': 'myhostname10',
'untrusted_caname': 'test_value_11'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssh_setting.fortios_firewall_ssh(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'host-trusted-checking': 'enable',
'hostkey-dsa1024': 'myhostname5',
'hostkey-ecdsa256': 'myhostname6',
'hostkey-ecdsa384': 'myhostname7',
'hostkey-ecdsa521': 'myhostname8',
'hostkey-ed25519': 'myhostname9',
'hostkey-rsa2048': 'myhostname10',
'untrusted-caname': 'test_value_11'
}
set_method_mock.assert_called_with('firewall.ssh', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,329 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_ssl_server
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_ssl_server.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssl_server_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_server': {
'add_header_x_forwarded_proto': 'enable',
'ip': 'test_value_4',
'mapped_port': '5',
'name': 'default_name_6',
'port': '7',
'ssl_algorithm': 'high',
'ssl_cert': 'test_value_9',
'ssl_client_renegotiation': 'allow',
'ssl_dh_bits': '768',
'ssl_max_version': 'tls-1.0',
'ssl_min_version': 'tls-1.0',
'ssl_mode': 'half',
'ssl_send_empty_frags': 'enable',
'url_rewrite': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_server.fortios_firewall(input_data, fos_instance)
expected_data = {
'add-header-x-forwarded-proto': 'enable',
'ip': 'test_value_4',
'mapped-port': '5',
'name': 'default_name_6',
'port': '7',
'ssl-algorithm': 'high',
'ssl-cert': 'test_value_9',
'ssl-client-renegotiation': 'allow',
'ssl-dh-bits': '768',
'ssl-max-version': 'tls-1.0',
'ssl-min-version': 'tls-1.0',
'ssl-mode': 'half',
'ssl-send-empty-frags': 'enable',
'url-rewrite': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-server', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssl_server_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_server': {
'add_header_x_forwarded_proto': 'enable',
'ip': 'test_value_4',
'mapped_port': '5',
'name': 'default_name_6',
'port': '7',
'ssl_algorithm': 'high',
'ssl_cert': 'test_value_9',
'ssl_client_renegotiation': 'allow',
'ssl_dh_bits': '768',
'ssl_max_version': 'tls-1.0',
'ssl_min_version': 'tls-1.0',
'ssl_mode': 'half',
'ssl_send_empty_frags': 'enable',
'url_rewrite': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_server.fortios_firewall(input_data, fos_instance)
expected_data = {
'add-header-x-forwarded-proto': 'enable',
'ip': 'test_value_4',
'mapped-port': '5',
'name': 'default_name_6',
'port': '7',
'ssl-algorithm': 'high',
'ssl-cert': 'test_value_9',
'ssl-client-renegotiation': 'allow',
'ssl-dh-bits': '768',
'ssl-max-version': 'tls-1.0',
'ssl-min-version': 'tls-1.0',
'ssl-mode': 'half',
'ssl-send-empty-frags': 'enable',
'url-rewrite': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-server', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssl_server_removal(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssl_server': {
'add_header_x_forwarded_proto': 'enable',
'ip': 'test_value_4',
'mapped_port': '5',
'name': 'default_name_6',
'port': '7',
'ssl_algorithm': 'high',
'ssl_cert': 'test_value_9',
'ssl_client_renegotiation': 'allow',
'ssl_dh_bits': '768',
'ssl_max_version': 'tls-1.0',
'ssl_min_version': 'tls-1.0',
'ssl_mode': 'half',
'ssl_send_empty_frags': 'enable',
'url_rewrite': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_server.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'ssl-server', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssl_server_deletion_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
input_data = {
'username': 'admin',
'state': 'absent',
'firewall_ssl_server': {
'add_header_x_forwarded_proto': 'enable',
'ip': 'test_value_4',
'mapped_port': '5',
'name': 'default_name_6',
'port': '7',
'ssl_algorithm': 'high',
'ssl_cert': 'test_value_9',
'ssl_client_renegotiation': 'allow',
'ssl_dh_bits': '768',
'ssl_max_version': 'tls-1.0',
'ssl_min_version': 'tls-1.0',
'ssl_mode': 'half',
'ssl_send_empty_frags': 'enable',
'url_rewrite': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_server.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'ssl-server', mkey=ANY, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssl_server_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_server': {
'add_header_x_forwarded_proto': 'enable',
'ip': 'test_value_4',
'mapped_port': '5',
'name': 'default_name_6',
'port': '7',
'ssl_algorithm': 'high',
'ssl_cert': 'test_value_9',
'ssl_client_renegotiation': 'allow',
'ssl_dh_bits': '768',
'ssl_max_version': 'tls-1.0',
'ssl_min_version': 'tls-1.0',
'ssl_mode': 'half',
'ssl_send_empty_frags': 'enable',
'url_rewrite': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_server.fortios_firewall(input_data, fos_instance)
expected_data = {
'add-header-x-forwarded-proto': 'enable',
'ip': 'test_value_4',
'mapped-port': '5',
'name': 'default_name_6',
'port': '7',
'ssl-algorithm': 'high',
'ssl-cert': 'test_value_9',
'ssl-client-renegotiation': 'allow',
'ssl-dh-bits': '768',
'ssl-max-version': 'tls-1.0',
'ssl-min-version': 'tls-1.0',
'ssl-mode': 'half',
'ssl-send-empty-frags': 'enable',
'url-rewrite': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-server', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_ssl_server_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_server': {
'random_attribute_not_valid': 'tag',
'add_header_x_forwarded_proto': 'enable',
'ip': 'test_value_4',
'mapped_port': '5',
'name': 'default_name_6',
'port': '7',
'ssl_algorithm': 'high',
'ssl_cert': 'test_value_9',
'ssl_client_renegotiation': 'allow',
'ssl_dh_bits': '768',
'ssl_max_version': 'tls-1.0',
'ssl_min_version': 'tls-1.0',
'ssl_mode': 'half',
'ssl_send_empty_frags': 'enable',
'url_rewrite': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_server.fortios_firewall(input_data, fos_instance)
expected_data = {
'add-header-x-forwarded-proto': 'enable',
'ip': 'test_value_4',
'mapped-port': '5',
'name': 'default_name_6',
'port': '7',
'ssl-algorithm': 'high',
'ssl-cert': 'test_value_9',
'ssl-client-renegotiation': 'allow',
'ssl-dh-bits': '768',
'ssl-max-version': 'tls-1.0',
'ssl-min-version': 'tls-1.0',
'ssl-mode': 'half',
'ssl-send-empty-frags': 'enable',
'url-rewrite': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-server', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200

@ -0,0 +1,231 @@
# Copyright 2019 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 <https://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import os
import json
import pytest
from mock import ANY
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
try:
from ansible.modules.network.fortios import fortios_firewall_ssl_setting
except ImportError:
pytest.skip("Could not load required modules for testing", allow_module_level=True)
@pytest.fixture(autouse=True)
def connection_mock(mocker):
connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_firewall_ssl_setting.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssl_setting_creation(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_setting': {
'abbreviate_handshake': 'enable',
'cert_cache_capacity': '4',
'cert_cache_timeout': '5',
'kxp_queue_threshold': '6',
'no_matching_cipher_action': 'bypass',
'proxy_connect_timeout': '8',
'session_cache_capacity': '9',
'session_cache_timeout': '10',
'ssl_dh_bits': '768',
'ssl_queue_threshold': '12',
'ssl_send_empty_frags': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_setting.fortios_firewall_ssl(input_data, fos_instance)
expected_data = {
'abbreviate-handshake': 'enable',
'cert-cache-capacity': '4',
'cert-cache-timeout': '5',
'kxp-queue-threshold': '6',
'no-matching-cipher-action': 'bypass',
'proxy-connect-timeout': '8',
'session-cache-capacity': '9',
'session-cache-timeout': '10',
'ssl-dh-bits': '768',
'ssl-queue-threshold': '12',
'ssl-send-empty-frags': 'enable'
}
set_method_mock.assert_called_with('firewall.ssl', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
def test_firewall_ssl_setting_creation_fails(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_setting': {
'abbreviate_handshake': 'enable',
'cert_cache_capacity': '4',
'cert_cache_timeout': '5',
'kxp_queue_threshold': '6',
'no_matching_cipher_action': 'bypass',
'proxy_connect_timeout': '8',
'session_cache_capacity': '9',
'session_cache_timeout': '10',
'ssl_dh_bits': '768',
'ssl_queue_threshold': '12',
'ssl_send_empty_frags': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_setting.fortios_firewall_ssl(input_data, fos_instance)
expected_data = {
'abbreviate-handshake': 'enable',
'cert-cache-capacity': '4',
'cert-cache-timeout': '5',
'kxp-queue-threshold': '6',
'no-matching-cipher-action': 'bypass',
'proxy-connect-timeout': '8',
'session-cache-capacity': '9',
'session-cache-timeout': '10',
'ssl-dh-bits': '768',
'ssl-queue-threshold': '12',
'ssl-send-empty-frags': 'enable'
}
set_method_mock.assert_called_with('firewall.ssl', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 500
def test_firewall_ssl_setting_idempotent(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_setting': {
'abbreviate_handshake': 'enable',
'cert_cache_capacity': '4',
'cert_cache_timeout': '5',
'kxp_queue_threshold': '6',
'no_matching_cipher_action': 'bypass',
'proxy_connect_timeout': '8',
'session_cache_capacity': '9',
'session_cache_timeout': '10',
'ssl_dh_bits': '768',
'ssl_queue_threshold': '12',
'ssl_send_empty_frags': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_setting.fortios_firewall_ssl(input_data, fos_instance)
expected_data = {
'abbreviate-handshake': 'enable',
'cert-cache-capacity': '4',
'cert-cache-timeout': '5',
'kxp-queue-threshold': '6',
'no-matching-cipher-action': 'bypass',
'proxy-connect-timeout': '8',
'session-cache-capacity': '9',
'session-cache-timeout': '10',
'ssl-dh-bits': '768',
'ssl-queue-threshold': '12',
'ssl-send-empty-frags': 'enable'
}
set_method_mock.assert_called_with('firewall.ssl', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert not changed
assert response['status'] == 'error'
assert response['http_status'] == 404
def test_firewall_ssl_setting_filter_foreign_attributes(mocker):
schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
input_data = {
'username': 'admin',
'state': 'present',
'firewall_ssl_setting': {
'random_attribute_not_valid': 'tag',
'abbreviate_handshake': 'enable',
'cert_cache_capacity': '4',
'cert_cache_timeout': '5',
'kxp_queue_threshold': '6',
'no_matching_cipher_action': 'bypass',
'proxy_connect_timeout': '8',
'session_cache_capacity': '9',
'session_cache_timeout': '10',
'ssl_dh_bits': '768',
'ssl_queue_threshold': '12',
'ssl_send_empty_frags': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_setting.fortios_firewall_ssl(input_data, fos_instance)
expected_data = {
'abbreviate-handshake': 'enable',
'cert-cache-capacity': '4',
'cert-cache-timeout': '5',
'kxp-queue-threshold': '6',
'no-matching-cipher-action': 'bypass',
'proxy-connect-timeout': '8',
'session-cache-capacity': '9',
'session-cache-timeout': '10',
'ssl-dh-bits': '768',
'ssl-queue-threshold': '12',
'ssl-send-empty-frags': 'enable'
}
set_method_mock.assert_called_with('firewall.ssl', 'setting', data=expected_data, vdom='root')
schema_method_mock.assert_not_called()
assert not is_error
assert changed
assert response['status'] == 'success'
assert response['http_status'] == 200
Loading…
Cancel
Save