FortiOS modules for 2.9 - 5 (#61062)

* FortiOS modules for 2.9 - 5

* Update fortios_firewall_vip.py

* Update fortios_firewall_vip6.py
pull/61170/head
Miguel Angel Muñoz González 5 years ago committed by Nilashish Chakraborty
parent 3373a2518a
commit 628aa3a808

@ -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_ttl_policy module: fortios_firewall_ttl_policy
short_description: Configure TTL policies in Fortinet's FortiOS and FortiGate. short_description: Configure TTL 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 ttl_policy category. user to set and modify firewall feature and ttl_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,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_ttl_policy: firewall_ttl_policy:
description: description:
- Configure TTL policies. - Configure TTL 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:
- Action to be performed on traffic matching this policy (default = deny). - Action to be performed on traffic matching this policy .
type: str
choices: choices:
- accept - accept
- deny - deny
@ -88,38 +99,47 @@ options:
description: description:
- ID. - ID.
required: true required: true
type: int
schedule: schedule:
description: description:
- Schedule object from available options. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group - Schedule object from available options. Source firewall.schedule.onetime.name firewall.schedule.recurring.name firewall.schedule.group
.name. .name.
type: str
service: service:
description: description:
- Service object(s) from available options. Separate multiple names with a space. - Service object(s) from available options. Separate multiple names with a space.
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:
- Source address object(s) from available options. Separate multiple names with a space. - Source address object(s) from available options. Separate multiple names with a space.
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
srcintf: srcintf:
description: description:
- Source interface name from available interfaces. Source system.zone.name system.interface.name. - Source interface name from available interfaces. Source system.zone.name system.interface.name.
type: str
status: status:
description: description:
- Enable/disable this TTL policy. - Enable/disable this TTL policy.
type: str
choices: choices:
- enable - enable
- disable - disable
ttl: ttl:
description: description:
- "Value/range to match against the packet's Time to Live value (format: ttl[ - ttl_high], 1 - 255)." - "Value/range to match against the packet's Time to Live value (format: ttl[ - ttl_high], 1 - 255)."
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -129,6 +149,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure TTL policies. - name: Configure TTL policies.
fortios_firewall_ttl_policy: fortios_firewall_ttl_policy:
@ -137,8 +158,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_ttl_policy: firewall_ttl_policy:
state: "present"
action: "accept" action: "accept"
id: "4" id: "4"
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)"
@ -213,14 +234,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']:
@ -228,7 +251,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_ttl_policy_data(json): def filter_firewall_ttl_policy_data(json):
@ -244,48 +267,66 @@ def filter_firewall_ttl_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_ttl_policy(data, fos): def firewall_ttl_policy(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_ttl_policy_data = data['firewall_ttl_policy'] firewall_ttl_policy_data = data['firewall_ttl_policy']
filtered_data = filter_firewall_ttl_policy_data(firewall_ttl_policy_data) filtered_data = underscore_to_hyphen(filter_firewall_ttl_policy_data(firewall_ttl_policy_data))
if firewall_ttl_policy_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'ttl-policy', 'ttl-policy',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_ttl_policy_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'ttl-policy', 'ttl-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_ttl_policy'] if data['firewall_ttl_policy']:
for method in methodlist: resp = firewall_ttl_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_ttl_policy": { "firewall_ttl_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"]}, "choices": ["accept", "deny"]},
"id": {"required": True, "type": "int"}, "id": {"required": True, "type": "int"},
@ -309,15 +350,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)

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
# Copyright 2018 Fortinet, Inc. # Copyright 2019 Fortinet, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -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_vip46 module: fortios_firewall_vip46
short_description: Configure IPv4 to IPv6 virtual IPs in Fortinet's FortiOS and FortiGate. short_description: Configure IPv4 to IPv6 virtual IPs 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 vip46 category. user to set and modify firewall feature and vip46 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,84 @@ 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: false 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_vip46: firewall_vip46:
description: description:
- Configure IPv4 to IPv6 virtual IPs. - Configure IPv4 to IPv6 virtual IPs.
default: null default: null
type: dict
suboptions: suboptions:
state: arp_reply:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
arp-reply:
description: description:
- Enable ARP reply. - Enable ARP reply.
type: str
choices: choices:
- disable - disable
- enable - enable
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
extip: extip:
description: description:
- Start-external-IP [-end-external-IP]. - Start-external-IP [-end-external-IP].
type: str
extport: extport:
description: description:
- External service port. - External service port.
type: str
id: id:
description: description:
- Custom defined id. - Custom defined id.
ldb-method: type: int
ldb_method:
description: description:
- Load balance method. - Load balance method.
type: str
choices: choices:
- static - static
- round-robin - round-robin
@ -112,69 +129,86 @@ options:
mappedip: mappedip:
description: description:
- Start-mapped-IP [-end mapped-IP]. - Start-mapped-IP [-end mapped-IP].
type: str
mappedport: mappedport:
description: description:
- Mapped service port. - Mapped service port.
type: str
monitor: monitor:
description: description:
- Health monitors. - Health monitors.
type: list
suboptions: suboptions:
name: name:
description: description:
- Health monitor name. Source firewall.ldb-monitor.name. - Health monitor name. Source firewall.ldb-monitor.name.
required: true required: true
type: str
name: name:
description: description:
- VIP46 name. - VIP46 name.
required: true required: true
type: str
portforward: portforward:
description: description:
- Enable port forwarding. - Enable port forwarding.
type: str
choices: choices:
- disable - disable
- enable - enable
protocol: protocol:
description: description:
- Mapped port protocol. - Mapped port protocol.
type: str
choices: choices:
- tcp - tcp
- udp - udp
realservers: realservers:
description: description:
- Real servers. - Real servers.
type: list
suboptions: suboptions:
client-ip: client_ip:
description: description:
- Restrict server to a client IP in this range. - Restrict server to a client IP in this range.
type: str
healthcheck: healthcheck:
description: description:
- Per server health check. - Per server health check.
type: str
choices: choices:
- disable - disable
- enable - enable
- vip - vip
holddown-interval: holddown_interval:
description: description:
- Hold down interval. - Hold down interval.
type: int
id: id:
description: description:
- Real server ID. - Real server ID.
required: true required: true
type: int
ip: ip:
description: description:
- Mapped server IPv6. - Mapped server IPv6.
max-connections: type: str
max_connections:
description: description:
- Maximum number of connections allowed to server. - Maximum number of connections allowed to server.
type: int
monitor: monitor:
description: description:
- Health monitors. Source firewall.ldb-monitor.name. - Health monitors. Source firewall.ldb-monitor.name.
type: str
port: port:
description: description:
- Mapped server port. - Mapped server port.
type: int
status: status:
description: description:
- Server administrative status. - Server administrative status.
type: str
choices: choices:
- active - active
- standby - standby
@ -182,31 +216,37 @@ options:
weight: weight:
description: description:
- weight - weight
server-type: type: int
server_type:
description: description:
- Server type. - Server type.
type: str
choices: choices:
- http - http
- tcp - tcp
- udp - udp
- ip - ip
src-filter: src_filter:
description: description:
- Source IP filter (x.x.x.x/x). - Source IP filter (x.x.x.x/x).
type: list
suboptions: suboptions:
range: range:
description: description:
- Src-filter range. - Src-filter range.
required: true required: true
type: str
type: type:
description: description:
- "VIP type: static NAT or server load balance." - "VIP type: static NAT or server load balance."
type: str
choices: choices:
- static-nat - static-nat
- server-load-balance - server-load-balance
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
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -216,6 +256,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPv4 to IPv6 virtual IPs. - name: Configure IPv4 to IPv6 virtual IPs.
fortios_firewall_vip46: fortios_firewall_vip46:
@ -223,15 +264,16 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False"
state: "present"
firewall_vip46: firewall_vip46:
state: "present" arp_reply: "disable"
arp-reply: "disable"
color: "4" color: "4"
comment: "Comment." comment: "Comment."
extip: "<your_own_value>" extip: "<your_own_value>"
extport: "<your_own_value>" extport: "<your_own_value>"
id: "8" id: "8"
ldb-method: "static" ldb_method: "static"
mappedip: "<your_own_value>" mappedip: "<your_own_value>"
mappedport: "<your_own_value>" mappedport: "<your_own_value>"
monitor: monitor:
@ -242,18 +284,18 @@ EXAMPLES = '''
protocol: "tcp" protocol: "tcp"
realservers: realservers:
- -
client-ip: "<your_own_value>" client_ip: "<your_own_value>"
healthcheck: "disable" healthcheck: "disable"
holddown-interval: "20" holddown_interval: "20"
id: "21" id: "21"
ip: "<your_own_value>" ip: "<your_own_value>"
max-connections: "23" max_connections: "23"
monitor: "<your_own_value> (source firewall.ldb-monitor.name)" monitor: "<your_own_value> (source firewall.ldb-monitor.name)"
port: "25" port: "25"
status: "active" status: "active"
weight: "27" weight: "27"
server-type: "http" server_type: "http"
src-filter: src_filter:
- -
range: "<your_own_value>" range: "<your_own_value>"
type: "static-nat" type: "static-nat"
@ -280,7 +322,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate description: Master key (id) used in the last call to FortiGate
returned: success returned: success
type: str type: str
sample: "key1" sample: "id"
name: name:
description: Name of the table used to fulfill the request description: Name of the table used to fulfill the request
returned: always returned: always
@ -320,14 +362,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,16 +379,16 @@ 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_vip46_data(json): def filter_firewall_vip46_data(json):
option_list = ['arp-reply', 'color', 'comment', option_list = ['arp_reply', 'color', 'comment',
'extip', 'extport', 'id', 'extip', 'extport', 'id',
'ldb-method', 'mappedip', 'mappedport', 'ldb_method', 'mappedip', 'mappedport',
'monitor', 'name', 'portforward', 'monitor', 'name', 'portforward',
'protocol', 'realservers', 'server-type', 'protocol', 'realservers', 'server_type',
'src-filter', 'type', 'uuid'] 'src_filter', 'type', 'uuid']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -354,56 +398,74 @@ def filter_firewall_vip46_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_vip46(data, fos): def firewall_vip46(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_vip46_data = data['firewall_vip46'] firewall_vip46_data = data['firewall_vip46']
filtered_data = filter_firewall_vip46_data(firewall_vip46_data) filtered_data = underscore_to_hyphen(filter_firewall_vip46_data(firewall_vip46_data))
if firewall_vip46_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'vip46', 'vip46',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_vip46_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'vip46', 'vip46',
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_vip46'] if data['firewall_vip46']:
for method in methodlist: resp = firewall_vip46(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": "False"}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_vip46": { "firewall_vip46": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "arp_reply": {"required": False, "type": "str",
"choices": ["present", "absent"]},
"arp-reply": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"extip": {"required": False, "type": "str"}, "extip": {"required": False, "type": "str"},
"extport": {"required": False, "type": "str"}, "extport": {"required": False, "type": "str"},
"id": {"required": False, "type": "int"}, "id": {"required": False, "type": "int"},
"ldb-method": {"required": False, "type": "str", "ldb_method": {"required": False, "type": "str",
"choices": ["static", "round-robin", "weighted", "choices": ["static", "round-robin", "weighted",
"least-session", "least-rtt", "first-alive"]}, "least-session", "least-rtt", "first-alive"]},
"mappedip": {"required": False, "type": "str"}, "mappedip": {"required": False, "type": "str"},
@ -419,23 +481,23 @@ def main():
"choices": ["tcp", "udp"]}, "choices": ["tcp", "udp"]},
"realservers": {"required": False, "type": "list", "realservers": {"required": False, "type": "list",
"options": { "options": {
"client-ip": {"required": False, "type": "str"}, "client_ip": {"required": False, "type": "str"},
"healthcheck": {"required": False, "type": "str", "healthcheck": {"required": False, "type": "str",
"choices": ["disable", "enable", "vip"]}, "choices": ["disable", "enable", "vip"]},
"holddown-interval": {"required": False, "type": "int"}, "holddown_interval": {"required": False, "type": "int"},
"id": {"required": True, "type": "int"}, "id": {"required": True, "type": "int"},
"ip": {"required": False, "type": "str"}, "ip": {"required": False, "type": "str"},
"max-connections": {"required": False, "type": "int"}, "max_connections": {"required": False, "type": "int"},
"monitor": {"required": False, "type": "str"}, "monitor": {"required": False, "type": "str"},
"port": {"required": False, "type": "int"}, "port": {"required": False, "type": "int"},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["active", "standby", "disable"]}, "choices": ["active", "standby", "disable"]},
"weight": {"required": False, "type": "int"} "weight": {"required": False, "type": "int"}
}}, }},
"server-type": {"required": False, "type": "str", "server_type": {"required": False, "type": "str",
"choices": ["http", "tcp", "udp", "choices": ["http", "tcp", "udp",
"ip"]}, "ip"]},
"src-filter": {"required": False, "type": "list", "src_filter": {"required": False, "type": "list",
"options": { "options": {
"range": {"required": True, "type": "str"} "range": {"required": True, "type": "str"}
}}, }},
@ -449,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)

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
# Copyright 2018 Fortinet, Inc. # Copyright 2019 Fortinet, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -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_vip64 module: fortios_firewall_vip64
short_description: Configure IPv6 to IPv4 virtual IPs in Fortinet's FortiOS and FortiGate. short_description: Configure IPv6 to IPv4 virtual IPs 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 vip64 category. user to set and modify firewall feature and vip64 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,84 @@ 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: false 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_vip64: firewall_vip64:
description: description:
- Configure IPv6 to IPv4 virtual IPs. - Configure IPv6 to IPv4 virtual IPs.
default: null default: null
type: dict
suboptions: suboptions:
state: arp_reply:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
arp-reply:
description: description:
- Enable ARP reply. - Enable ARP reply.
type: str
choices: choices:
- disable - disable
- enable - enable
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
extip: extip:
description: description:
- Start-external-IP [-end-external-IP]. - Start-external-IP [-end-external-IP].
type: str
extport: extport:
description: description:
- External service port. - External service port.
type: str
id: id:
description: description:
- Custom defined id. - Custom defined id.
ldb-method: type: int
ldb_method:
description: description:
- Load balance method. - Load balance method.
type: str
choices: choices:
- static - static
- round-robin - round-robin
@ -112,69 +129,86 @@ options:
mappedip: mappedip:
description: description:
- Start-mapped-IP [-end-mapped-IP]. - Start-mapped-IP [-end-mapped-IP].
type: str
mappedport: mappedport:
description: description:
- Mapped service port. - Mapped service port.
type: str
monitor: monitor:
description: description:
- Health monitors. - Health monitors.
type: list
suboptions: suboptions:
name: name:
description: description:
- Health monitor name. Source firewall.ldb-monitor.name. - Health monitor name. Source firewall.ldb-monitor.name.
required: true required: true
type: str
name: name:
description: description:
- VIP64 name. - VIP64 name.
required: true required: true
type: str
portforward: portforward:
description: description:
- Enable port forwarding. - Enable port forwarding.
type: str
choices: choices:
- disable - disable
- enable - enable
protocol: protocol:
description: description:
- Mapped port protocol. - Mapped port protocol.
type: str
choices: choices:
- tcp - tcp
- udp - udp
realservers: realservers:
description: description:
- Real servers. - Real servers.
type: list
suboptions: suboptions:
client-ip: client_ip:
description: description:
- Restrict server to a client IP in this range. - Restrict server to a client IP in this range.
type: str
healthcheck: healthcheck:
description: description:
- Per server health check. - Per server health check.
type: str
choices: choices:
- disable - disable
- enable - enable
- vip - vip
holddown-interval: holddown_interval:
description: description:
- Hold down interval. - Hold down interval.
type: int
id: id:
description: description:
- Real server ID. - Real server ID.
required: true required: true
type: int
ip: ip:
description: description:
- Mapped server IP. - Mapped server IP.
max-connections: type: str
max_connections:
description: description:
- Maximum number of connections allowed to server. - Maximum number of connections allowed to server.
type: int
monitor: monitor:
description: description:
- Health monitors. Source firewall.ldb-monitor.name. - Health monitors. Source firewall.ldb-monitor.name.
type: str
port: port:
description: description:
- Mapped server port. - Mapped server port.
type: int
status: status:
description: description:
- Server administrative status. - Server administrative status.
type: str
choices: choices:
- active - active
- standby - standby
@ -182,31 +216,37 @@ options:
weight: weight:
description: description:
- weight - weight
server-type: type: int
server_type:
description: description:
- Server type. - Server type.
type: str
choices: choices:
- http - http
- tcp - tcp
- udp - udp
- ip - ip
src-filter: src_filter:
description: description:
- "Source IP6 filter (x:x:x:x:x:x:x:x/x)." - "Source IP6 filter (x:x:x:x:x:x:x:x/x)."
type: list
suboptions: suboptions:
range: range:
description: description:
- Src-filter range. - Src-filter range.
required: true required: true
type: str
type: type:
description: description:
- "VIP type: static NAT or server load balance." - "VIP type: static NAT or server load balance."
type: str
choices: choices:
- static-nat - static-nat
- server-load-balance - server-load-balance
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
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -216,6 +256,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPv6 to IPv4 virtual IPs. - name: Configure IPv6 to IPv4 virtual IPs.
fortios_firewall_vip64: fortios_firewall_vip64:
@ -223,15 +264,16 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False"
state: "present"
firewall_vip64: firewall_vip64:
state: "present" arp_reply: "disable"
arp-reply: "disable"
color: "4" color: "4"
comment: "Comment." comment: "Comment."
extip: "<your_own_value>" extip: "<your_own_value>"
extport: "<your_own_value>" extport: "<your_own_value>"
id: "8" id: "8"
ldb-method: "static" ldb_method: "static"
mappedip: "<your_own_value>" mappedip: "<your_own_value>"
mappedport: "<your_own_value>" mappedport: "<your_own_value>"
monitor: monitor:
@ -242,18 +284,18 @@ EXAMPLES = '''
protocol: "tcp" protocol: "tcp"
realservers: realservers:
- -
client-ip: "<your_own_value>" client_ip: "<your_own_value>"
healthcheck: "disable" healthcheck: "disable"
holddown-interval: "20" holddown_interval: "20"
id: "21" id: "21"
ip: "<your_own_value>" ip: "<your_own_value>"
max-connections: "23" max_connections: "23"
monitor: "<your_own_value> (source firewall.ldb-monitor.name)" monitor: "<your_own_value> (source firewall.ldb-monitor.name)"
port: "25" port: "25"
status: "active" status: "active"
weight: "27" weight: "27"
server-type: "http" server_type: "http"
src-filter: src_filter:
- -
range: "<your_own_value>" range: "<your_own_value>"
type: "static-nat" type: "static-nat"
@ -280,7 +322,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate description: Master key (id) used in the last call to FortiGate
returned: success returned: success
type: str type: str
sample: "key1" sample: "id"
name: name:
description: Name of the table used to fulfill the request description: Name of the table used to fulfill the request
returned: always returned: always
@ -320,14 +362,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,16 +379,16 @@ 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_vip64_data(json): def filter_firewall_vip64_data(json):
option_list = ['arp-reply', 'color', 'comment', option_list = ['arp_reply', 'color', 'comment',
'extip', 'extport', 'id', 'extip', 'extport', 'id',
'ldb-method', 'mappedip', 'mappedport', 'ldb_method', 'mappedip', 'mappedport',
'monitor', 'name', 'portforward', 'monitor', 'name', 'portforward',
'protocol', 'realservers', 'server-type', 'protocol', 'realservers', 'server_type',
'src-filter', 'type', 'uuid'] 'src_filter', 'type', 'uuid']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -354,56 +398,74 @@ def filter_firewall_vip64_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_vip64(data, fos): def firewall_vip64(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_vip64_data = data['firewall_vip64'] firewall_vip64_data = data['firewall_vip64']
filtered_data = filter_firewall_vip64_data(firewall_vip64_data) filtered_data = underscore_to_hyphen(filter_firewall_vip64_data(firewall_vip64_data))
if firewall_vip64_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'vip64', 'vip64',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_vip64_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'vip64', 'vip64',
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_vip64'] if data['firewall_vip64']:
for method in methodlist: resp = firewall_vip64(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": "False"}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_vip64": { "firewall_vip64": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "arp_reply": {"required": False, "type": "str",
"choices": ["present", "absent"]},
"arp-reply": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"color": {"required": False, "type": "int"}, "color": {"required": False, "type": "int"},
"comment": {"required": False, "type": "str"}, "comment": {"required": False, "type": "str"},
"extip": {"required": False, "type": "str"}, "extip": {"required": False, "type": "str"},
"extport": {"required": False, "type": "str"}, "extport": {"required": False, "type": "str"},
"id": {"required": False, "type": "int"}, "id": {"required": False, "type": "int"},
"ldb-method": {"required": False, "type": "str", "ldb_method": {"required": False, "type": "str",
"choices": ["static", "round-robin", "weighted", "choices": ["static", "round-robin", "weighted",
"least-session", "least-rtt", "first-alive"]}, "least-session", "least-rtt", "first-alive"]},
"mappedip": {"required": False, "type": "str"}, "mappedip": {"required": False, "type": "str"},
@ -419,23 +481,23 @@ def main():
"choices": ["tcp", "udp"]}, "choices": ["tcp", "udp"]},
"realservers": {"required": False, "type": "list", "realservers": {"required": False, "type": "list",
"options": { "options": {
"client-ip": {"required": False, "type": "str"}, "client_ip": {"required": False, "type": "str"},
"healthcheck": {"required": False, "type": "str", "healthcheck": {"required": False, "type": "str",
"choices": ["disable", "enable", "vip"]}, "choices": ["disable", "enable", "vip"]},
"holddown-interval": {"required": False, "type": "int"}, "holddown_interval": {"required": False, "type": "int"},
"id": {"required": True, "type": "int"}, "id": {"required": True, "type": "int"},
"ip": {"required": False, "type": "str"}, "ip": {"required": False, "type": "str"},
"max-connections": {"required": False, "type": "int"}, "max_connections": {"required": False, "type": "int"},
"monitor": {"required": False, "type": "str"}, "monitor": {"required": False, "type": "str"},
"port": {"required": False, "type": "int"}, "port": {"required": False, "type": "int"},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["active", "standby", "disable"]}, "choices": ["active", "standby", "disable"]},
"weight": {"required": False, "type": "int"} "weight": {"required": False, "type": "int"}
}}, }},
"server-type": {"required": False, "type": "str", "server_type": {"required": False, "type": "str",
"choices": ["http", "tcp", "udp", "choices": ["http", "tcp", "udp",
"ip"]}, "ip"]},
"src-filter": {"required": False, "type": "list", "src_filter": {"required": False, "type": "list",
"options": { "options": {
"range": {"required": True, "type": "str"} "range": {"required": True, "type": "str"}
}}, }},
@ -449,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)

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
# Copyright 2018 Fortinet, Inc. # Copyright 2019 Fortinet, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -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_vipgrp module: fortios_firewall_vipgrp
short_description: Configure IPv4 virtual IP groups in Fortinet's FortiOS and FortiGate. short_description: Configure IPv4 virtual IP 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 feature and vipgrp category. user to set and modify firewall feature and vipgrp 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,84 @@ 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: false 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_vipgrp: firewall_vipgrp:
description: description:
- Configure IPv4 virtual IP groups. - Configure IPv4 virtual IP 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:
- Integer value to determine the color of the icon in the GUI (range 1 to 32, default = 0, which sets the value to 1). - Integer value to determine the color of the icon in the GUI (range 1 to 32).
type: int
comments: comments:
description: description:
- Comment. - Comment.
type: str
interface: interface:
description: description:
- interface Source system.interface.name. - interface Source system.interface.name.
type: str
member: member:
description: description:
- Member VIP objects of the group (Separate multiple objects with a space). - Member VIP objects of the group (Separate multiple objects with a space).
type: list
suboptions: suboptions:
name: name:
description: description:
- VIP name. Source firewall.vip.name. - VIP name. Source firewall.vip.name.
required: true required: true
type: str
name: name:
description: description:
- VIP group name. - VIP group name.
required: true required: true
type: str
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
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -111,6 +128,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPv4 virtual IP groups. - name: Configure IPv4 virtual IP groups.
fortios_firewall_vipgrp: fortios_firewall_vipgrp:
@ -118,8 +136,9 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False"
state: "present"
firewall_vipgrp: firewall_vipgrp:
state: "present"
color: "3" color: "3"
comments: "<your_own_value>" comments: "<your_own_value>"
interface: "<your_own_value> (source system.interface.name)" interface: "<your_own_value> (source system.interface.name)"
@ -150,7 +169,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate description: Master key (id) used in the last call to FortiGate
returned: success returned: success
type: str type: str
sample: "key1" sample: "id"
name: name:
description: Name of the table used to fulfill the request description: Name of the table used to fulfill the request
returned: always returned: always
@ -190,14 +209,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
fos = None
def login(data, fos):
def login(data):
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 +226,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_vipgrp_data(json): def filter_firewall_vipgrp_data(json):
@ -220,48 +241,66 @@ def filter_firewall_vipgrp_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_vipgrp(data, fos): def firewall_vipgrp(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_vipgrp_data = data['firewall_vipgrp'] firewall_vipgrp_data = data['firewall_vipgrp']
filtered_data = filter_firewall_vipgrp_data(firewall_vipgrp_data) filtered_data = underscore_to_hyphen(filter_firewall_vipgrp_data(firewall_vipgrp_data))
if firewall_vipgrp_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'vipgrp', 'vipgrp',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_vipgrp_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'vipgrp', 'vipgrp',
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_vipgrp'] if data['firewall_vipgrp']:
for method in methodlist: resp = firewall_vipgrp(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": "False"}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_vipgrp": { "firewall_vipgrp": {
"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"},
"comments": {"required": False, "type": "str"}, "comments": {"required": False, "type": "str"},
"interface": {"required": False, "type": "str"}, "interface": {"required": False, "type": "str"},
@ -278,15 +317,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)

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
# Copyright 2018 Fortinet, Inc. # Copyright 2019 Fortinet, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -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_vipgrp46 module: fortios_firewall_vipgrp46
short_description: Configure IPv4 to IPv6 virtual IP groups in Fortinet's FortiOS and FortiGate. short_description: Configure IPv4 to IPv6 virtual IP 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 feature and vipgrp46 category. user to set and modify firewall feature and vipgrp46 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 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: false 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_vipgrp46: firewall_vipgrp46:
description: description:
- Configure IPv4 to IPv6 virtual IP groups. - Configure IPv4 to IPv6 virtual IP 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:
- Integer value to determine the color of the icon in the GUI (range 1 to 32, default = 0, which sets the value to 1). - Integer value to determine the color of the icon in the GUI (range 1 to 32).
type: int
comments: comments:
description: description:
- Comment. - Comment.
type: str
member: member:
description: description:
- Member VIP objects of the group (Separate multiple objects with a space). - Member VIP objects of the group (Separate multiple objects with a space).
type: list
suboptions: suboptions:
name: name:
description: description:
- VIP46 name. Source firewall.vip46.name. - VIP46 name. Source firewall.vip46.name.
required: true required: true
type: str
name: name:
description: description:
- VIP46 group name. - VIP46 group name.
required: true required: true
type: str
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
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -108,6 +124,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPv4 to IPv6 virtual IP groups. - name: Configure IPv4 to IPv6 virtual IP groups.
fortios_firewall_vipgrp46: fortios_firewall_vipgrp46:
@ -115,8 +132,9 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False"
state: "present"
firewall_vipgrp46: firewall_vipgrp46:
state: "present"
color: "3" color: "3"
comments: "<your_own_value>" comments: "<your_own_value>"
member: member:
@ -146,7 +164,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate description: Master key (id) used in the last call to FortiGate
returned: success returned: success
type: str type: str
sample: "key1" sample: "id"
name: name:
description: Name of the table used to fulfill the request description: Name of the table used to fulfill the request
returned: always returned: always
@ -186,14 +204,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
fos = None
def login(data, fos):
def login(data):
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']:
@ -201,7 +221,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_vipgrp46_data(json): def filter_firewall_vipgrp46_data(json):
@ -216,48 +236,66 @@ def filter_firewall_vipgrp46_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_vipgrp46(data, fos): def firewall_vipgrp46(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_vipgrp46_data = data['firewall_vipgrp46'] firewall_vipgrp46_data = data['firewall_vipgrp46']
filtered_data = filter_firewall_vipgrp46_data(firewall_vipgrp46_data) filtered_data = underscore_to_hyphen(filter_firewall_vipgrp46_data(firewall_vipgrp46_data))
if firewall_vipgrp46_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'vipgrp46', 'vipgrp46',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_vipgrp46_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'vipgrp46', 'vipgrp46',
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_vipgrp46'] if data['firewall_vipgrp46']:
for method in methodlist: resp = firewall_vipgrp46(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": "False"}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_vipgrp46": { "firewall_vipgrp46": {
"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"},
"comments": {"required": False, "type": "str"}, "comments": {"required": False, "type": "str"},
"member": {"required": False, "type": "list", "member": {"required": False, "type": "list",
@ -273,15 +311,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)

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
# Copyright 2018 Fortinet, Inc. # Copyright 2019 Fortinet, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -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_vipgrp6 module: fortios_firewall_vipgrp6
short_description: Configure IPv6 virtual IP groups in Fortinet's FortiOS and FortiGate. short_description: Configure IPv6 virtual IP 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 feature and vipgrp6 category. user to set and modify firewall feature and vipgrp6 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 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: false 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_vipgrp6: firewall_vipgrp6:
description: description:
- Configure IPv6 virtual IP groups. - Configure IPv6 virtual IP 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:
- Integer value to determine the color of the icon in the GUI (range 1 to 32, default = 0, which sets the value to 1). - Integer value to determine the color of the icon in the GUI (range 1 to 32).
type: int
comments: comments:
description: description:
- Comment. - Comment.
type: str
member: member:
description: description:
- Member VIP objects of the group (Separate multiple objects with a space). - Member VIP objects of the group (Separate multiple objects with a space).
type: list
suboptions: suboptions:
name: name:
description: description:
- IPv6 VIP name. Source firewall.vip6.name. - IPv6 VIP name. Source firewall.vip6.name.
required: true required: true
type: str
name: name:
description: description:
- IPv6 VIP group name. - IPv6 VIP group name.
required: true required: true
type: str
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
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -108,6 +124,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPv6 virtual IP groups. - name: Configure IPv6 virtual IP groups.
fortios_firewall_vipgrp6: fortios_firewall_vipgrp6:
@ -115,8 +132,9 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False"
state: "present"
firewall_vipgrp6: firewall_vipgrp6:
state: "present"
color: "3" color: "3"
comments: "<your_own_value>" comments: "<your_own_value>"
member: member:
@ -146,7 +164,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate description: Master key (id) used in the last call to FortiGate
returned: success returned: success
type: str type: str
sample: "key1" sample: "id"
name: name:
description: Name of the table used to fulfill the request description: Name of the table used to fulfill the request
returned: always returned: always
@ -186,14 +204,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
fos = None
def login(data, fos):
def login(data):
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']:
@ -201,7 +221,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_vipgrp6_data(json): def filter_firewall_vipgrp6_data(json):
@ -216,48 +236,66 @@ def filter_firewall_vipgrp6_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_vipgrp6(data, fos): def firewall_vipgrp6(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_vipgrp6_data = data['firewall_vipgrp6'] firewall_vipgrp6_data = data['firewall_vipgrp6']
filtered_data = filter_firewall_vipgrp6_data(firewall_vipgrp6_data) filtered_data = underscore_to_hyphen(filter_firewall_vipgrp6_data(firewall_vipgrp6_data))
if firewall_vipgrp6_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'vipgrp6', 'vipgrp6',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_vipgrp6_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'vipgrp6', 'vipgrp6',
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_vipgrp6'] if data['firewall_vipgrp6']:
for method in methodlist: resp = firewall_vipgrp6(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": "False"}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_vipgrp6": { "firewall_vipgrp6": {
"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"},
"comments": {"required": False, "type": "str"}, "comments": {"required": False, "type": "str"},
"member": {"required": False, "type": "list", "member": {"required": False, "type": "list",
@ -273,15 +311,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)

@ -1,6 +1,6 @@
#!/usr/bin/python #!/usr/bin/python
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
# Copyright 2018 Fortinet, Inc. # Copyright 2019 Fortinet, Inc.
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
@ -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_vipgrp64 module: fortios_firewall_vipgrp64
short_description: Configure IPv6 to IPv4 virtual IP groups in Fortinet's FortiOS and FortiGate. short_description: Configure IPv6 to IPv4 virtual IP 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 feature and vipgrp64 category. user to set and modify firewall feature and vipgrp64 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 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: false 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_vipgrp64: firewall_vipgrp64:
description: description:
- Configure IPv6 to IPv4 virtual IP groups. - Configure IPv6 to IPv4 virtual IP 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:
- Integer value to determine the color of the icon in the GUI (range 1 to 32, default = 0, which sets the value to 1). - Integer value to determine the color of the icon in the GUI (range 1 to 32).
type: int
comments: comments:
description: description:
- Comment. - Comment.
type: str
member: member:
description: description:
- Member VIP objects of the group (Separate multiple objects with a space). - Member VIP objects of the group (Separate multiple objects with a space).
type: list
suboptions: suboptions:
name: name:
description: description:
- VIP64 name. Source firewall.vip64.name. - VIP64 name. Source firewall.vip64.name.
required: true required: true
type: str
name: name:
description: description:
- VIP64 group name. - VIP64 group name.
required: true required: true
type: str
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
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -108,6 +124,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPv6 to IPv4 virtual IP groups. - name: Configure IPv6 to IPv4 virtual IP groups.
fortios_firewall_vipgrp64: fortios_firewall_vipgrp64:
@ -115,8 +132,9 @@ EXAMPLES = '''
username: "{{ username }}" username: "{{ username }}"
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False"
state: "present"
firewall_vipgrp64: firewall_vipgrp64:
state: "present"
color: "3" color: "3"
comments: "<your_own_value>" comments: "<your_own_value>"
member: member:
@ -146,7 +164,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate description: Master key (id) used in the last call to FortiGate
returned: success returned: success
type: str type: str
sample: "key1" sample: "id"
name: name:
description: Name of the table used to fulfill the request description: Name of the table used to fulfill the request
returned: always returned: always
@ -186,14 +204,16 @@ version:
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
from ansible.module_utils.network.fortios.fortios import FortiOSHandler
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
fos = None
def login(data, fos):
def login(data):
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']:
@ -201,7 +221,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_vipgrp64_data(json): def filter_firewall_vipgrp64_data(json):
@ -216,48 +236,66 @@ def filter_firewall_vipgrp64_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_vipgrp64(data, fos): def firewall_vipgrp64(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_vipgrp64_data = data['firewall_vipgrp64'] firewall_vipgrp64_data = data['firewall_vipgrp64']
filtered_data = filter_firewall_vipgrp64_data(firewall_vipgrp64_data) filtered_data = underscore_to_hyphen(filter_firewall_vipgrp64_data(firewall_vipgrp64_data))
if firewall_vipgrp64_data['state'] == "present":
if state == "present":
return fos.set('firewall', return fos.set('firewall',
'vipgrp64', 'vipgrp64',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_vipgrp64_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall', return fos.delete('firewall',
'vipgrp64', 'vipgrp64',
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_vipgrp64'] if data['firewall_vipgrp64']:
for method in methodlist: resp = firewall_vipgrp64(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": "False"}, "https": {"required": False, "type": "bool", "default": True},
"ssl_verify": {"required": False, "type": "bool", "default": True},
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"firewall_vipgrp64": { "firewall_vipgrp64": {
"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"},
"comments": {"required": False, "type": "str"}, "comments": {"required": False, "type": "str"},
"member": {"required": False, "type": "list", "member": {"required": False, "type": "list",
@ -273,15 +311,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_wildcard_fqdn_custom module: fortios_firewall_wildcard_fqdn_custom
short_description: Config global/VDOM Wildcard FQDN address in Fortinet's FortiOS and FortiGate. short_description: Config global/VDOM Wildcard FQDN address 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_wildcard_fqdn feature and custom category. user to set and modify firewall_wildcard_fqdn 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,62 +41,81 @@ 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_wildcard_fqdn_custom: firewall_wildcard_fqdn_custom:
description: description:
- Config global/VDOM Wildcard FQDN address. - Config global/VDOM Wildcard FQDN address.
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:
- GUI icon color. - GUI icon color.
type: int
comment: comment:
description: description:
- Comment. - Comment.
type: str
name: name:
description: description:
- Address name. - Address name.
required: true required: true
type: str
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 address visibility. - Enable/disable address visibility.
type: str
choices: choices:
- enable - enable
- disable - disable
wildcard-fqdn: wildcard_fqdn:
description: description:
- Wildcard FQDN. - Wildcard FQDN.
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -109,6 +125,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Config global/VDOM Wildcard FQDN address. - name: Config global/VDOM Wildcard FQDN address.
fortios_firewall_wildcard_fqdn_custom: fortios_firewall_wildcard_fqdn_custom:
@ -117,14 +134,14 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_wildcard_fqdn_custom: firewall_wildcard_fqdn_custom:
state: "present"
color: "3" color: "3"
comment: "Comment." comment: "Comment."
name: "default_name_5" name: "default_name_5"
uuid: "<your_own_value>" uuid: "<your_own_value>"
visibility: "enable" visibility: "enable"
wildcard-fqdn: "<your_own_value>" wildcard_fqdn: "<your_own_value>"
''' '''
RETURN = ''' RETURN = '''
@ -187,14 +204,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']:
@ -202,12 +221,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_wildcard_fqdn_custom_data(json): def filter_firewall_wildcard_fqdn_custom_data(json):
option_list = ['color', 'comment', 'name', option_list = ['color', 'comment', 'name',
'uuid', 'visibility', 'wildcard-fqdn'] 'uuid', 'visibility', 'wildcard_fqdn']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -217,55 +236,73 @@ def filter_firewall_wildcard_fqdn_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_wildcard_fqdn_custom(data, fos): def firewall_wildcard_fqdn_custom(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_wildcard_fqdn_custom_data = data['firewall_wildcard_fqdn_custom'] firewall_wildcard_fqdn_custom_data = data['firewall_wildcard_fqdn_custom']
filtered_data = filter_firewall_wildcard_fqdn_custom_data(firewall_wildcard_fqdn_custom_data) filtered_data = underscore_to_hyphen(filter_firewall_wildcard_fqdn_custom_data(firewall_wildcard_fqdn_custom_data))
if firewall_wildcard_fqdn_custom_data['state'] == "present":
if state == "present":
return fos.set('firewall.wildcard-fqdn', return fos.set('firewall.wildcard-fqdn',
'custom', 'custom',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_wildcard_fqdn_custom_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.wildcard-fqdn', return fos.delete('firewall.wildcard-fqdn',
'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_wildcard_fqdn(data, fos): def fortios_firewall_wildcard_fqdn(data, fos):
login(data)
methodlist = ['firewall_wildcard_fqdn_custom'] if data['firewall_wildcard_fqdn_custom']:
for method in methodlist: resp = firewall_wildcard_fqdn_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_wildcard_fqdn_custom": { "firewall_wildcard_fqdn_custom": {
"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"},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"uuid": {"required": False, "type": "str"}, "uuid": {"required": False, "type": "str"},
"visibility": {"required": False, "type": "str", "visibility": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"wildcard-fqdn": {"required": False, "type": "str"} "wildcard_fqdn": {"required": False, "type": "str"}
} }
} }
@ -273,15 +310,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_wildcard_fqdn(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_wildcard_fqdn(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_wildcard_fqdn(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_wildcard_fqdn_group module: fortios_firewall_wildcard_fqdn_group
short_description: Config global Wildcard FQDN address groups in Fortinet's FortiOS and FortiGate. short_description: Config global Wildcard FQDN address 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_wildcard_fqdn feature and group category. user to set and modify firewall_wildcard_fqdn 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,64 +41,84 @@ 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_wildcard_fqdn_group: firewall_wildcard_fqdn_group:
description: description:
- Config global Wildcard FQDN address groups. - Config global Wildcard FQDN address 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:
- GUI icon color. - GUI icon color.
type: int
comment: comment:
description: description:
- Comment. - Comment.
type: str
member: member:
description: description:
- Address group members. - Address group members.
type: list
suboptions: suboptions:
name: name:
description: description:
- Address name. Source firewall.wildcard-fqdn.custom.name. - Address name. Source firewall.wildcard-fqdn.custom.name.
required: true required: true
type: str
name: name:
description: description:
- Address group name. - Address group name.
required: true required: true
type: str
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 address visibility. - Enable/disable address visibility.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -114,6 +131,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Config global Wildcard FQDN address groups. - name: Config global Wildcard FQDN address groups.
fortios_firewall_wildcard_fqdn_group: fortios_firewall_wildcard_fqdn_group:
@ -122,8 +140,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
firewall_wildcard_fqdn_group: firewall_wildcard_fqdn_group:
state: "present"
color: "3" color: "3"
comment: "Comment." comment: "Comment."
member: member:
@ -194,14 +212,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']:
@ -209,7 +229,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_wildcard_fqdn_group_data(json): def filter_firewall_wildcard_fqdn_group_data(json):
@ -224,48 +244,66 @@ def filter_firewall_wildcard_fqdn_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_wildcard_fqdn_group(data, fos): def firewall_wildcard_fqdn_group(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
firewall_wildcard_fqdn_group_data = data['firewall_wildcard_fqdn_group'] firewall_wildcard_fqdn_group_data = data['firewall_wildcard_fqdn_group']
filtered_data = filter_firewall_wildcard_fqdn_group_data(firewall_wildcard_fqdn_group_data) filtered_data = underscore_to_hyphen(filter_firewall_wildcard_fqdn_group_data(firewall_wildcard_fqdn_group_data))
if firewall_wildcard_fqdn_group_data['state'] == "present":
if state == "present":
return fos.set('firewall.wildcard-fqdn', return fos.set('firewall.wildcard-fqdn',
'group', 'group',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif firewall_wildcard_fqdn_group_data['state'] == "absent": elif state == "absent":
return fos.delete('firewall.wildcard-fqdn', return fos.delete('firewall.wildcard-fqdn',
'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_wildcard_fqdn(data, fos): def fortios_firewall_wildcard_fqdn(data, fos):
login(data)
methodlist = ['firewall_wildcard_fqdn_group'] if data['firewall_wildcard_fqdn_group']:
for method in methodlist: resp = firewall_wildcard_fqdn_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_wildcard_fqdn_group": { "firewall_wildcard_fqdn_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",
@ -283,15 +321,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_wildcard_fqdn(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_wildcard_fqdn(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_firewall_wildcard_fqdn(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_ftp_proxy_explicit module: fortios_ftp_proxy_explicit
short_description: Configure explicit FTP proxy settings in Fortinet's FortiOS and FortiGate. short_description: Configure explicit FTP 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 ftp_proxy feature and explicit category. user to set and modify ftp_proxy feature and explicit 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,52 +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
ftp_proxy_explicit: ftp_proxy_explicit:
description: description:
- Configure explicit FTP proxy settings. - Configure explicit FTP proxy settings.
default: null default: null
type: dict
suboptions: suboptions:
incoming-ip: incoming_ip:
description: description:
- Accept incoming FTP requests from this IP address. An interface must have this IP address. - Accept incoming FTP requests from this IP address. An interface must have this IP address.
incoming-port: type: str
incoming_port:
description: description:
- Accept incoming FTP requests on one or more ports. - Accept incoming FTP requests on one or more ports.
outgoing-ip: type: str
outgoing_ip:
description: description:
- Outgoing FTP requests will leave from this IP address. An interface must have this IP address. - Outgoing FTP requests will leave from this IP address. An interface must have this IP address.
sec-default-action: type: str
sec_default_action:
description: description:
- Accept or deny explicit FTP proxy sessions when no FTP proxy firewall policy exists. - Accept or deny explicit FTP proxy sessions when no FTP proxy firewall policy exists.
type: str
choices: choices:
- accept - accept
- deny - deny
status: status:
description: description:
- Enable/disable the explicit FTP proxy. - Enable/disable the explicit FTP proxy.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -102,6 +114,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure explicit FTP proxy settings. - name: Configure explicit FTP proxy settings.
fortios_ftp_proxy_explicit: fortios_ftp_proxy_explicit:
@ -111,10 +124,10 @@ EXAMPLES = '''
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
ftp_proxy_explicit: ftp_proxy_explicit:
incoming-ip: "<your_own_value>" incoming_ip: "<your_own_value>"
incoming-port: "<your_own_value>" incoming_port: "<your_own_value>"
outgoing-ip: "<your_own_value>" outgoing_ip: "<your_own_value>"
sec-default-action: "accept" sec_default_action: "accept"
status: "enable" status: "enable"
''' '''
@ -178,14 +191,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']:
@ -193,12 +208,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_ftp_proxy_explicit_data(json): def filter_ftp_proxy_explicit_data(json):
option_list = ['incoming-ip', 'incoming-port', 'outgoing-ip', option_list = ['incoming_ip', 'incoming_port', 'outgoing_ip',
'sec-default-action', 'status'] 'sec_default_action', 'status']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -208,43 +223,60 @@ def filter_ftp_proxy_explicit_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 ftp_proxy_explicit(data, fos): def ftp_proxy_explicit(data, fos):
vdom = data['vdom'] vdom = data['vdom']
ftp_proxy_explicit_data = data['ftp_proxy_explicit'] ftp_proxy_explicit_data = data['ftp_proxy_explicit']
filtered_data = filter_ftp_proxy_explicit_data(ftp_proxy_explicit_data) filtered_data = underscore_to_hyphen(filter_ftp_proxy_explicit_data(ftp_proxy_explicit_data))
return fos.set('ftp-proxy', return fos.set('ftp-proxy',
'explicit', 'explicit',
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_ftp_proxy(data, fos): def fortios_ftp_proxy(data, fos):
login(data)
methodlist = ['ftp_proxy_explicit'] if data['ftp_proxy_explicit']:
for method in methodlist: resp = ftp_proxy_explicit(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},
"ftp_proxy_explicit": { "ftp_proxy_explicit": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"incoming-ip": {"required": False, "type": "str"}, "incoming_ip": {"required": False, "type": "str"},
"incoming-port": {"required": False, "type": "str"}, "incoming_port": {"required": False, "type": "str"},
"outgoing-ip": {"required": False, "type": "str"}, "outgoing_ip": {"required": False, "type": "str"},
"sec-default-action": {"required": False, "type": "str", "sec_default_action": {"required": False, "type": "str",
"choices": ["accept", "deny"]}, "choices": ["accept", "deny"]},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["enable", "disable"]} "choices": ["enable", "disable"]}
@ -255,15 +287,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_ftp_proxy(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_ftp_proxy(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_ftp_proxy(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_icap_profile module: fortios_icap_profile
short_description: Configure ICAP profiles in Fortinet's FortiOS and FortiGate. short_description: Configure ICAP 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 icap feature and profile category. user to set and modify icap feature and 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,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
icap_profile: icap_profile:
description: description:
- Configure ICAP profiles. - Configure ICAP profiles.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
methods: methods:
description: description:
- The allowed HTTP methods that will be sent to ICAP server for further processing. - The allowed HTTP methods that will be sent to ICAP server for further processing.
type: str
choices: choices:
- delete - delete
- get - get
@ -94,48 +105,59 @@ options:
description: description:
- ICAP profile name. - ICAP profile name.
required: true required: true
replacemsg-group: type: str
replacemsg_group:
description: description:
- Replacement message group. Source system.replacemsg-group.name. - Replacement message group. Source system.replacemsg-group.name.
type: str
request: request:
description: description:
- Enable/disable whether an HTTP request is passed to an ICAP server. - Enable/disable whether an HTTP request is passed to an ICAP server.
type: str
choices: choices:
- disable - disable
- enable - enable
request-failure: request_failure:
description: description:
- Action to take if the ICAP server cannot be contacted when processing an HTTP request. - Action to take if the ICAP server cannot be contacted when processing an HTTP request.
type: str
choices: choices:
- error - error
- bypass - bypass
request-path: request_path:
description: description:
- Path component of the ICAP URI that identifies the HTTP request processing service. - Path component of the ICAP URI that identifies the HTTP request processing service.
request-server: type: str
request_server:
description: description:
- ICAP server to use for an HTTP request. Source icap.server.name. - ICAP server to use for an HTTP request. Source icap.server.name.
type: str
response: response:
description: description:
- Enable/disable whether an HTTP response is passed to an ICAP server. - Enable/disable whether an HTTP response is passed to an ICAP server.
type: str
choices: choices:
- disable - disable
- enable - enable
response-failure: response_failure:
description: description:
- Action to take if the ICAP server cannot be contacted when processing an HTTP response. - Action to take if the ICAP server cannot be contacted when processing an HTTP response.
type: str
choices: choices:
- error - error
- bypass - bypass
response-path: response_path:
description: description:
- Path component of the ICAP URI that identifies the HTTP response processing service. - Path component of the ICAP URI that identifies the HTTP response processing service.
response-server: type: str
response_server:
description: description:
- ICAP server to use for an HTTP response. Source icap.server.name. - ICAP server to use for an HTTP response. Source icap.server.name.
streaming-content-bypass: type: str
streaming_content_bypass:
description: description:
- Enable/disable bypassing of ICAP server for streaming content. - Enable/disable bypassing of ICAP server for streaming content.
type: str
choices: choices:
- disable - disable
- enable - enable
@ -148,6 +170,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure ICAP profiles. - name: Configure ICAP profiles.
fortios_icap_profile: fortios_icap_profile:
@ -156,20 +179,20 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
icap_profile: icap_profile:
state: "present"
methods: "delete" methods: "delete"
name: "default_name_4" name: "default_name_4"
replacemsg-group: "<your_own_value> (source system.replacemsg-group.name)" replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)"
request: "disable" request: "disable"
request-failure: "error" request_failure: "error"
request-path: "<your_own_value>" request_path: "<your_own_value>"
request-server: "<your_own_value> (source icap.server.name)" request_server: "<your_own_value> (source icap.server.name)"
response: "disable" response: "disable"
response-failure: "error" response_failure: "error"
response-path: "<your_own_value>" response_path: "<your_own_value>"
response-server: "<your_own_value> (source icap.server.name)" response_server: "<your_own_value> (source icap.server.name)"
streaming-content-bypass: "disable" streaming_content_bypass: "disable"
''' '''
RETURN = ''' RETURN = '''
@ -232,14 +255,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']:
@ -247,14 +272,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_icap_profile_data(json): def filter_icap_profile_data(json):
option_list = ['methods', 'name', 'replacemsg-group', option_list = ['methods', 'name', 'replacemsg_group',
'request', 'request-failure', 'request-path', 'request', 'request_failure', 'request_path',
'request-server', 'response', 'response-failure', 'request_server', 'response', 'response_failure',
'response-path', 'response-server', 'streaming-content-bypass'] 'response_path', 'response_server', 'streaming_content_bypass']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -264,67 +289,85 @@ def filter_icap_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 icap_profile(data, fos): def icap_profile(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
icap_profile_data = data['icap_profile'] icap_profile_data = data['icap_profile']
filtered_data = filter_icap_profile_data(icap_profile_data) filtered_data = underscore_to_hyphen(filter_icap_profile_data(icap_profile_data))
if icap_profile_data['state'] == "present":
if state == "present":
return fos.set('icap', return fos.set('icap',
'profile', 'profile',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif icap_profile_data['state'] == "absent": elif state == "absent":
return fos.delete('icap', return fos.delete('icap',
'profile', 'profile',
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_icap(data, fos): def fortios_icap(data, fos):
login(data)
methodlist = ['icap_profile'] if data['icap_profile']:
for method in methodlist: resp = icap_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"]},
"icap_profile": { "icap_profile": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"methods": {"required": False, "type": "str", "methods": {"required": False, "type": "str",
"choices": ["delete", "get", "head", "choices": ["delete", "get", "head",
"options", "post", "put", "options", "post", "put",
"trace", "other"]}, "trace", "other"]},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"replacemsg-group": {"required": False, "type": "str"}, "replacemsg_group": {"required": False, "type": "str"},
"request": {"required": False, "type": "str", "request": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"request-failure": {"required": False, "type": "str", "request_failure": {"required": False, "type": "str",
"choices": ["error", "bypass"]}, "choices": ["error", "bypass"]},
"request-path": {"required": False, "type": "str"}, "request_path": {"required": False, "type": "str"},
"request-server": {"required": False, "type": "str"}, "request_server": {"required": False, "type": "str"},
"response": {"required": False, "type": "str", "response": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"response-failure": {"required": False, "type": "str", "response_failure": {"required": False, "type": "str",
"choices": ["error", "bypass"]}, "choices": ["error", "bypass"]},
"response-path": {"required": False, "type": "str"}, "response_path": {"required": False, "type": "str"},
"response-server": {"required": False, "type": "str"}, "response_server": {"required": False, "type": "str"},
"streaming-content-bypass": {"required": False, "type": "str", "streaming_content_bypass": {"required": False, "type": "str",
"choices": ["disable", "enable"]} "choices": ["disable", "enable"]}
} }
@ -333,15 +376,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_icap(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_icap(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_icap(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_icap_server module: fortios_icap_server
short_description: Configure ICAP servers in Fortinet's FortiOS and FortiGate. short_description: Configure ICAP 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 icap feature and server category. user to set and modify icap feature and 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,62 +41,81 @@ 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
icap_server: icap_server:
description: description:
- Configure ICAP servers. - Configure ICAP servers.
default: null default: null
type: dict
suboptions: suboptions:
state: ip_address:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
ip-address:
description: description:
- IPv4 address of the ICAP server. - IPv4 address of the ICAP server.
ip-version: type: str
ip_version:
description: description:
- IP version. - IP version.
type: str
choices: choices:
- 4 - 4
- 6 - 6
ip6-address: ip6_address:
description: description:
- IPv6 address of the ICAP server. - IPv6 address of the ICAP server.
max-connections: type: str
max_connections:
description: description:
- Maximum number of concurrent connections to ICAP server. - Maximum number of concurrent connections to ICAP server.
type: int
name: name:
description: description:
- Server name. - Server name.
required: true required: true
type: str
port: port:
description: description:
- ICAP server port. - ICAP server port.
type: int
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -109,6 +125,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure ICAP servers. - name: Configure ICAP servers.
fortios_icap_server: fortios_icap_server:
@ -117,12 +134,12 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
icap_server: icap_server:
state: "present" ip_address: "<your_own_value>"
ip-address: "<your_own_value>" ip_version: "4"
ip-version: "4" ip6_address: "<your_own_value>"
ip6-address: "<your_own_value>" max_connections: "6"
max-connections: "6"
name: "default_name_7" name: "default_name_7"
port: "8" port: "8"
''' '''
@ -187,14 +204,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']:
@ -202,12 +221,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_icap_server_data(json): def filter_icap_server_data(json):
option_list = ['ip-address', 'ip-version', 'ip6-address', option_list = ['ip_address', 'ip_version', 'ip6_address',
'max-connections', 'name', 'port'] 'max_connections', 'name', 'port']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -217,53 +236,71 @@ def filter_icap_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 icap_server(data, fos): def icap_server(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
icap_server_data = data['icap_server'] icap_server_data = data['icap_server']
filtered_data = filter_icap_server_data(icap_server_data) filtered_data = underscore_to_hyphen(filter_icap_server_data(icap_server_data))
if icap_server_data['state'] == "present":
if state == "present":
return fos.set('icap', return fos.set('icap',
'server', 'server',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif icap_server_data['state'] == "absent": elif state == "absent":
return fos.delete('icap', return fos.delete('icap',
'server', '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_icap(data, fos): def fortios_icap(data, fos):
login(data)
methodlist = ['icap_server'] if data['icap_server']:
for method in methodlist: resp = icap_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"]},
"icap_server": { "icap_server": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str", "ip_address": {"required": False, "type": "str"},
"choices": ["present", "absent"]}, "ip_version": {"required": False, "type": "str",
"ip-address": {"required": False, "type": "str"},
"ip-version": {"required": False, "type": "str",
"choices": ["4", "6"]}, "choices": ["4", "6"]},
"ip6-address": {"required": False, "type": "str"}, "ip6_address": {"required": False, "type": "str"},
"max-connections": {"required": False, "type": "int"}, "max_connections": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"port": {"required": False, "type": "int"} "port": {"required": False, "type": "int"}
@ -273,15 +310,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_icap(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_icap(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_icap(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_ips_custom module: fortios_ips_custom
short_description: Configure IPS custom signature in Fortinet's FortiOS and FortiGate. short_description: Configure IPS custom signature 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 ips feature and custom category. user to set and modify ips 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,88 +41,114 @@ 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
ips_custom: ips_custom:
description: description:
- Configure IPS custom signature. - Configure IPS custom signature.
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:
- Default action (pass or block) for this signature. - Default action (pass or block) for this signature.
type: str
choices: choices:
- pass - pass
- block - block
application: application:
description: description:
- Applications to be protected. Blank for all applications. - Applications to be protected. Blank for all applications.
type: str
comment: comment:
description: description:
- Comment. - Comment.
type: str
location: location:
description: description:
- Protect client or server traffic. - Protect client or server traffic.
type: str
log: log:
description: description:
- Enable/disable logging. - Enable/disable logging.
type: str
choices: choices:
- disable - disable
- enable - enable
log-packet: log_packet:
description: description:
- Enable/disable packet logging. - Enable/disable packet logging.
type: str
choices: choices:
- disable - disable
- enable - enable
os: os:
description: description:
- Operating system(s) that the signature protects. Blank for all operating systems. - Operating system(s) that the signature protects. Blank for all operating systems.
type: str
protocol: protocol:
description: description:
- Protocol(s) that the signature scans. Blank for all protocols. - Protocol(s) that the signature scans. Blank for all protocols.
rule-id: type: str
rule_id:
description: description:
- Signature ID. - Signature ID.
type: int
severity: severity:
description: description:
- Relative severity of the signature, from info to critical. Log messages generated by the signature include the severity. - Relative severity of the signature, from info to critical. Log messages generated by the signature include the severity.
sig-name: type: str
sig_name:
description: description:
- Signature name. - Signature name.
type: str
signature: signature:
description: description:
- Custom signature enclosed in single quotes. - Custom signature enclosed in single quotes.
type: str
status: status:
description: description:
- Enable/disable this signature. - Enable/disable this signature.
type: str
choices: choices:
- disable - disable
- enable - enable
@ -133,6 +156,7 @@ options:
description: description:
- Signature tag. - Signature tag.
required: true required: true
type: str
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -142,6 +166,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPS custom signature. - name: Configure IPS custom signature.
fortios_ips_custom: fortios_ips_custom:
@ -150,19 +175,19 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
ips_custom: ips_custom:
state: "present"
action: "pass" action: "pass"
application: "<your_own_value>" application: "<your_own_value>"
comment: "Comment." comment: "Comment."
location: "<your_own_value>" location: "<your_own_value>"
log: "disable" log: "disable"
log-packet: "disable" log_packet: "disable"
os: "<your_own_value>" os: "<your_own_value>"
protocol: "<your_own_value>" protocol: "<your_own_value>"
rule-id: "11" rule_id: "11"
severity: "<your_own_value>" severity: "<your_own_value>"
sig-name: "<your_own_value>" sig_name: "<your_own_value>"
signature: "<your_own_value>" signature: "<your_own_value>"
status: "disable" status: "disable"
tag: "<your_own_value>" tag: "<your_own_value>"
@ -228,14 +253,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']:
@ -243,14 +270,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_ips_custom_data(json): def filter_ips_custom_data(json):
option_list = ['action', 'application', 'comment', option_list = ['action', 'application', 'comment',
'location', 'log', 'log-packet', 'location', 'log', 'log_packet',
'os', 'protocol', 'rule-id', 'os', 'protocol', 'rule_id',
'severity', 'sig-name', 'signature', 'severity', 'sig_name', 'signature',
'status', 'tag'] 'status', 'tag']
dictionary = {} dictionary = {}
@ -261,48 +288,66 @@ def filter_ips_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 ips_custom(data, fos): def ips_custom(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
ips_custom_data = data['ips_custom'] ips_custom_data = data['ips_custom']
filtered_data = filter_ips_custom_data(ips_custom_data) filtered_data = underscore_to_hyphen(filter_ips_custom_data(ips_custom_data))
if ips_custom_data['state'] == "present":
if state == "present":
return fos.set('ips', return fos.set('ips',
'custom', 'custom',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif ips_custom_data['state'] == "absent": elif state == "absent":
return fos.delete('ips', return fos.delete('ips',
'custom', 'custom',
mkey=filtered_data['tag'], mkey=filtered_data['tag'],
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_ips(data, fos): def fortios_ips(data, fos):
login(data)
methodlist = ['ips_custom'] if data['ips_custom']:
for method in methodlist: resp = ips_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"]},
"ips_custom": { "ips_custom": {
"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": ["pass", "block"]}, "choices": ["pass", "block"]},
"application": {"required": False, "type": "str"}, "application": {"required": False, "type": "str"},
@ -310,13 +355,13 @@ def main():
"location": {"required": False, "type": "str"}, "location": {"required": False, "type": "str"},
"log": {"required": False, "type": "str", "log": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"log-packet": {"required": False, "type": "str", "log_packet": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"os": {"required": False, "type": "str"}, "os": {"required": False, "type": "str"},
"protocol": {"required": False, "type": "str"}, "protocol": {"required": False, "type": "str"},
"rule-id": {"required": False, "type": "int"}, "rule_id": {"required": False, "type": "int"},
"severity": {"required": False, "type": "str"}, "severity": {"required": False, "type": "str"},
"sig-name": {"required": False, "type": "str"}, "sig_name": {"required": False, "type": "str"},
"signature": {"required": False, "type": "str"}, "signature": {"required": False, "type": "str"},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
@ -328,15 +373,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_ips(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_ips(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_ips(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_ips_decoder module: fortios_ips_decoder
short_description: Configure IPS decoder in Fortinet's FortiOS and FortiGate. short_description: Configure IPS decoder 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 ips feature and decoder category. user to set and modify ips feature and decoder 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
ips_decoder: ips_decoder:
description: description:
- Configure IPS decoder. - Configure IPS decoder.
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:
- Decoder name. - Decoder name.
required: true required: true
type: str
parameter: parameter:
description: description:
- IPS group parameters. - IPS group parameters.
type: list
suboptions: suboptions:
name: name:
description: description:
- Parameter name. - Parameter name.
required: true required: true
type: str
value: value:
description: description:
- Parameter value. - Parameter value.
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: Configure IPS decoder. - name: Configure IPS decoder.
fortios_ips_decoder: fortios_ips_decoder:
@ -110,8 +125,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
ips_decoder: ips_decoder:
state: "present"
name: "default_name_3" name: "default_name_3"
parameter: parameter:
- -
@ -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_ips_decoder_data(json): def filter_ips_decoder_data(json):
@ -208,48 +225,66 @@ def filter_ips_decoder_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 ips_decoder(data, fos): def ips_decoder(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
ips_decoder_data = data['ips_decoder'] ips_decoder_data = data['ips_decoder']
filtered_data = filter_ips_decoder_data(ips_decoder_data) filtered_data = underscore_to_hyphen(filter_ips_decoder_data(ips_decoder_data))
if ips_decoder_data['state'] == "present":
if state == "present":
return fos.set('ips', return fos.set('ips',
'decoder', 'decoder',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif ips_decoder_data['state'] == "absent": elif state == "absent":
return fos.delete('ips', return fos.delete('ips',
'decoder', 'decoder',
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_ips(data, fos): def fortios_ips(data, fos):
login(data)
methodlist = ['ips_decoder'] if data['ips_decoder']:
for method in methodlist: resp = ips_decoder(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"]},
"ips_decoder": { "ips_decoder": {
"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"},
"parameter": {"required": False, "type": "list", "parameter": {"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_ips(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_ips(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_ips(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_ips_global module: fortios_ips_global
short_description: Configure IPS global parameter in Fortinet's FortiOS and FortiGate. short_description: Configure IPS global parameter 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 ips feature and global category. user to set and modify ips feature and global 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,37 +41,48 @@ 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
ips_global: ips_global:
description: description:
- Configure IPS global parameter. - Configure IPS global parameter.
default: null default: null
type: dict
suboptions: suboptions:
anomaly-mode: anomaly_mode:
description: description:
- Global blocking mode for rate-based anomalies. - Global blocking mode for rate-based anomalies.
type: str
choices: choices:
- periodical - periodical
- continuous - continuous
@ -82,59 +90,71 @@ options:
description: description:
- Regular or extended IPS database. Regular protects against the latest common and in-the-wild attacks. Extended includes protection from - Regular or extended IPS database. Regular protects against the latest common and in-the-wild attacks. Extended includes protection from
legacy attacks. legacy attacks.
type: str
choices: choices:
- regular - regular
- extended - extended
deep-app-insp-db-limit: deep_app_insp_db_limit:
description: description:
- Limit on number of entries in deep application inspection database (1 - 2147483647, 0 = use recommended setting) - Limit on number of entries in deep application inspection database (1 - 2147483647, 0 = use recommended setting)
deep-app-insp-timeout: type: int
deep_app_insp_timeout:
description: description:
- Timeout for Deep application inspection (1 - 2147483647 sec., 0 = use recommended setting). - Timeout for Deep application inspection (1 - 2147483647 sec., 0 = use recommended setting).
engine-count: type: int
engine_count:
description: description:
- Number of IPS engines running. If set to the default value of 0, FortiOS sets the number to optimize performance depending on the number - Number of IPS engines running. If set to the default value of 0, FortiOS sets the number to optimize performance depending on the number
of CPU cores. of CPU cores.
exclude-signatures: type: int
exclude_signatures:
description: description:
- Excluded signatures. - Excluded signatures.
type: str
choices: choices:
- none - none
- industrial - industrial
fail-open: fail_open:
description: description:
- Enable to allow traffic if the IPS process crashes. Default is disable and IPS traffic is blocked when the IPS process crashes. - Enable to allow traffic if the IPS process crashes. Default is disable and IPS traffic is blocked when the IPS process crashes.
type: str
choices: choices:
- enable - enable
- disable - disable
intelligent-mode: intelligent_mode:
description: description:
- Enable/disable IPS adaptive scanning (intelligent mode). Intelligent mode optimizes the scanning method for the type of traffic. - Enable/disable IPS adaptive scanning (intelligent mode). Intelligent mode optimizes the scanning method for the type of traffic.
type: str
choices: choices:
- enable - enable
- disable - disable
session-limit-mode: session_limit_mode:
description: description:
- Method of counting concurrent sessions used by session limit anomalies. Choose between greater accuracy (accurate) or improved - Method of counting concurrent sessions used by session limit anomalies. Choose between greater accuracy (accurate) or improved
performance (heuristics). performance (heuristics).
type: str
choices: choices:
- accurate - accurate
- heuristic - heuristic
skype-client-public-ipaddr: skype_client_public_ipaddr:
description: description:
- Public IP addresses of your network that receive Skype sessions. Helps identify Skype sessions. Separate IP addresses with commas. - Public IP addresses of your network that receive Skype sessions. Helps identify Skype sessions. Separate IP addresses with commas.
socket-size: type: str
socket_size:
description: description:
- IPS socket buffer size (0 - 256 MB). Default depends on available memory. Can be changed to tune performance. - IPS socket buffer size (0 - 256 MB). Default depends on available memory. Can be changed to tune performance.
sync-session-ttl: type: int
sync_session_ttl:
description: description:
- Enable/disable use of kernel session TTL for IPS sessions. - Enable/disable use of kernel session TTL for IPS sessions.
type: str
choices: choices:
- enable - enable
- disable - disable
traffic-submit: traffic_submit:
description: description:
- Enable/disable submitting attack data found by this FortiGate to FortiGuard. - Enable/disable submitting attack data found by this FortiGate to FortiGuard.
type: str
choices: choices:
- enable - enable
- disable - disable
@ -147,6 +167,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPS global parameter. - name: Configure IPS global parameter.
fortios_ips_global: fortios_ips_global:
@ -156,19 +177,19 @@ EXAMPLES = '''
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
ips_global: ips_global:
anomaly-mode: "periodical" anomaly_mode: "periodical"
database: "regular" database: "regular"
deep-app-insp-db-limit: "5" deep_app_insp_db_limit: "5"
deep-app-insp-timeout: "6" deep_app_insp_timeout: "6"
engine-count: "7" engine_count: "7"
exclude-signatures: "none" exclude_signatures: "none"
fail-open: "enable" fail_open: "enable"
intelligent-mode: "enable" intelligent_mode: "enable"
session-limit-mode: "accurate" session_limit_mode: "accurate"
skype-client-public-ipaddr: "<your_own_value>" skype_client_public_ipaddr: "<your_own_value>"
socket-size: "13" socket_size: "13"
sync-session-ttl: "enable" sync_session_ttl: "enable"
traffic-submit: "enable" traffic_submit: "enable"
''' '''
RETURN = ''' RETURN = '''
@ -231,14 +252,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']:
@ -246,15 +269,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_ips_global_data(json): def filter_ips_global_data(json):
option_list = ['anomaly-mode', 'database', 'deep-app-insp-db-limit', option_list = ['anomaly_mode', 'database', 'deep_app_insp_db_limit',
'deep-app-insp-timeout', 'engine-count', 'exclude-signatures', 'deep_app_insp_timeout', 'engine_count', 'exclude_signatures',
'fail-open', 'intelligent-mode', 'session-limit-mode', 'fail_open', 'intelligent_mode', 'session_limit_mode',
'skype-client-public-ipaddr', 'socket-size', 'sync-session-ttl', 'skype_client_public_ipaddr', 'socket_size', 'sync_session_ttl',
'traffic-submit'] 'traffic_submit']
dictionary = {} dictionary = {}
for attribute in option_list: for attribute in option_list:
@ -264,59 +287,76 @@ def filter_ips_global_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 ips_global(data, fos): def ips_global(data, fos):
vdom = data['vdom'] vdom = data['vdom']
ips_global_data = data['ips_global'] ips_global_data = data['ips_global']
filtered_data = filter_ips_global_data(ips_global_data) filtered_data = underscore_to_hyphen(filter_ips_global_data(ips_global_data))
return fos.set('ips', return fos.set('ips',
'global', 'global',
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_ips(data, fos): def fortios_ips(data, fos):
login(data)
methodlist = ['ips_global'] if data['ips_global']:
for method in methodlist: resp = ips_global(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},
"ips_global": { "ips_global": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"anomaly-mode": {"required": False, "type": "str", "anomaly_mode": {"required": False, "type": "str",
"choices": ["periodical", "continuous"]}, "choices": ["periodical", "continuous"]},
"database": {"required": False, "type": "str", "database": {"required": False, "type": "str",
"choices": ["regular", "extended"]}, "choices": ["regular", "extended"]},
"deep-app-insp-db-limit": {"required": False, "type": "int"}, "deep_app_insp_db_limit": {"required": False, "type": "int"},
"deep-app-insp-timeout": {"required": False, "type": "int"}, "deep_app_insp_timeout": {"required": False, "type": "int"},
"engine-count": {"required": False, "type": "int"}, "engine_count": {"required": False, "type": "int"},
"exclude-signatures": {"required": False, "type": "str", "exclude_signatures": {"required": False, "type": "str",
"choices": ["none", "industrial"]}, "choices": ["none", "industrial"]},
"fail-open": {"required": False, "type": "str", "fail_open": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"intelligent-mode": {"required": False, "type": "str", "intelligent_mode": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"session-limit-mode": {"required": False, "type": "str", "session_limit_mode": {"required": False, "type": "str",
"choices": ["accurate", "heuristic"]}, "choices": ["accurate", "heuristic"]},
"skype-client-public-ipaddr": {"required": False, "type": "str"}, "skype_client_public_ipaddr": {"required": False, "type": "str"},
"socket-size": {"required": False, "type": "int"}, "socket_size": {"required": False, "type": "int"},
"sync-session-ttl": {"required": False, "type": "str", "sync_session_ttl": {"required": False, "type": "str",
"choices": ["enable", "disable"]}, "choices": ["enable", "disable"]},
"traffic-submit": {"required": False, "type": "str", "traffic_submit": {"required": False, "type": "str",
"choices": ["enable", "disable"]} "choices": ["enable", "disable"]}
} }
@ -325,15 +365,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_ips(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_ips(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_ips(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_ips_rule module: fortios_ips_rule
short_description: Configure IPS rules in Fortinet's FortiOS and FortiGate. short_description: Configure IPS rules 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 ips feature and rule category. user to set and modify ips feature and rule 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,106 +41,137 @@ 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
ips_rule: ips_rule:
description: description:
- Configure IPS rules. - Configure IPS rules.
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:
- Action. - Action.
type: str
choices: choices:
- pass - pass
- block - block
application: application:
description: description:
- Vulnerable applications. - Vulnerable applications.
type: str
date: date:
description: description:
- Date. - Date.
type: int
group: group:
description: description:
- Group. - Group.
type: str
location: location:
description: description:
- Vulnerable location. - Vulnerable location.
type: str
log: log:
description: description:
- Enable/disable logging. - Enable/disable logging.
type: str
choices: choices:
- disable - disable
- enable - enable
log-packet: log_packet:
description: description:
- Enable/disable packet logging. - Enable/disable packet logging.
type: str
choices: choices:
- disable - disable
- enable - enable
metadata: metadata:
description: description:
- Meta data. - Meta data.
type: list
suboptions: suboptions:
id: id:
description: description:
- ID. - ID.
required: true required: true
type: int
metaid: metaid:
description: description:
- Meta ID. - Meta ID.
type: int
valueid: valueid:
description: description:
- Value ID. - Value ID.
type: int
name: name:
description: description:
- Rule name. - Rule name.
required: true required: true
type: str
os: os:
description: description:
- Vulnerable operation systems. - Vulnerable operation systems.
type: str
rev: rev:
description: description:
- Revision. - Revision.
rule-id: type: int
rule_id:
description: description:
- Rule ID. - Rule ID.
type: int
service: service:
description: description:
- Vulnerable service. - Vulnerable service.
type: str
severity: severity:
description: description:
- Severity. - Severity.
type: str
status: status:
description: description:
- Enable/disable status. - Enable/disable status.
type: str
choices: choices:
- disable - disable
- enable - enable
@ -156,6 +184,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPS rules. - name: Configure IPS rules.
fortios_ips_rule: fortios_ips_rule:
@ -164,15 +193,15 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
ips_rule: ips_rule:
state: "present"
action: "pass" action: "pass"
application: "<your_own_value>" application: "<your_own_value>"
date: "5" date: "5"
group: "<your_own_value>" group: "<your_own_value>"
location: "<your_own_value>" location: "<your_own_value>"
log: "disable" log: "disable"
log-packet: "disable" log_packet: "disable"
metadata: metadata:
- -
id: "11" id: "11"
@ -181,7 +210,7 @@ EXAMPLES = '''
name: "default_name_14" name: "default_name_14"
os: "<your_own_value>" os: "<your_own_value>"
rev: "16" rev: "16"
rule-id: "17" rule_id: "17"
service: "<your_own_value>" service: "<your_own_value>"
severity: "<your_own_value>" severity: "<your_own_value>"
status: "disable" status: "disable"
@ -247,14 +276,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']:
@ -262,14 +293,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_ips_rule_data(json): def filter_ips_rule_data(json):
option_list = ['action', 'application', 'date', option_list = ['action', 'application', 'date',
'group', 'location', 'log', 'group', 'location', 'log',
'log-packet', 'metadata', 'name', 'log_packet', 'metadata', 'name',
'os', 'rev', 'rule-id', 'os', 'rev', 'rule_id',
'service', 'severity', 'status'] 'service', 'severity', 'status']
dictionary = {} dictionary = {}
@ -280,48 +311,66 @@ def filter_ips_rule_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 ips_rule(data, fos): def ips_rule(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
ips_rule_data = data['ips_rule'] ips_rule_data = data['ips_rule']
filtered_data = filter_ips_rule_data(ips_rule_data) filtered_data = underscore_to_hyphen(filter_ips_rule_data(ips_rule_data))
if ips_rule_data['state'] == "present":
if state == "present":
return fos.set('ips', return fos.set('ips',
'rule', 'rule',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif ips_rule_data['state'] == "absent": elif state == "absent":
return fos.delete('ips', return fos.delete('ips',
'rule', 'rule',
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_ips(data, fos): def fortios_ips(data, fos):
login(data)
methodlist = ['ips_rule'] if data['ips_rule']:
for method in methodlist: resp = ips_rule(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"]},
"ips_rule": { "ips_rule": {
"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": ["pass", "block"]}, "choices": ["pass", "block"]},
"application": {"required": False, "type": "str"}, "application": {"required": False, "type": "str"},
@ -330,7 +379,7 @@ def main():
"location": {"required": False, "type": "str"}, "location": {"required": False, "type": "str"},
"log": {"required": False, "type": "str", "log": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"log-packet": {"required": False, "type": "str", "log_packet": {"required": False, "type": "str",
"choices": ["disable", "enable"]}, "choices": ["disable", "enable"]},
"metadata": {"required": False, "type": "list", "metadata": {"required": False, "type": "list",
"options": { "options": {
@ -341,7 +390,7 @@ def main():
"name": {"required": True, "type": "str"}, "name": {"required": True, "type": "str"},
"os": {"required": False, "type": "str"}, "os": {"required": False, "type": "str"},
"rev": {"required": False, "type": "int"}, "rev": {"required": False, "type": "int"},
"rule-id": {"required": False, "type": "int"}, "rule_id": {"required": False, "type": "int"},
"service": {"required": False, "type": "str"}, "service": {"required": False, "type": "str"},
"severity": {"required": False, "type": "str"}, "severity": {"required": False, "type": "str"},
"status": {"required": False, "type": "str", "status": {"required": False, "type": "str",
@ -353,15 +402,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_ips(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_ips(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_ips(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_ips_rule_settings module: fortios_ips_rule_settings
short_description: Configure IPS rule setting in Fortinet's FortiOS and FortiGate. short_description: Configure IPS rule setting 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 ips feature and rule_settings category. user to set and modify ips feature and rule_settings 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,44 +41,58 @@ 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
ips_rule_settings: ips_rule_settings:
description: description:
- Configure IPS rule setting. - Configure IPS rule setting.
default: null default: null
type: dict
suboptions: suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
id: id:
description: description:
- Rule ID. - Rule ID.
required: true required: true
type: int
''' '''
EXAMPLES = ''' EXAMPLES = '''
@ -91,6 +102,7 @@ EXAMPLES = '''
username: "admin" username: "admin"
password: "" password: ""
vdom: "root" vdom: "root"
ssl_verify: "False"
tasks: tasks:
- name: Configure IPS rule setting. - name: Configure IPS rule setting.
fortios_ips_rule_settings: fortios_ips_rule_settings:
@ -99,8 +111,8 @@ EXAMPLES = '''
password: "{{ password }}" password: "{{ password }}"
vdom: "{{ vdom }}" vdom: "{{ vdom }}"
https: "False" https: "False"
state: "present"
ips_rule_settings: ips_rule_settings:
state: "present"
id: "3" id: "3"
''' '''
@ -164,14 +176,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']:
@ -179,7 +193,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_ips_rule_settings_data(json): def filter_ips_rule_settings_data(json):
@ -193,48 +207,66 @@ def filter_ips_rule_settings_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 ips_rule_settings(data, fos): def ips_rule_settings(data, fos):
vdom = data['vdom'] vdom = data['vdom']
state = data['state']
ips_rule_settings_data = data['ips_rule_settings'] ips_rule_settings_data = data['ips_rule_settings']
filtered_data = filter_ips_rule_settings_data(ips_rule_settings_data) filtered_data = underscore_to_hyphen(filter_ips_rule_settings_data(ips_rule_settings_data))
if ips_rule_settings_data['state'] == "present":
if state == "present":
return fos.set('ips', return fos.set('ips',
'rule-settings', 'rule-settings',
data=filtered_data, data=filtered_data,
vdom=vdom) vdom=vdom)
elif ips_rule_settings_data['state'] == "absent": elif state == "absent":
return fos.delete('ips', return fos.delete('ips',
'rule-settings', 'rule-settings',
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_ips(data, fos): def fortios_ips(data, fos):
login(data)
methodlist = ['ips_rule_settings'] if data['ips_rule_settings']:
for method in methodlist: resp = ips_rule_settings(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"]},
"ips_rule_settings": { "ips_rule_settings": {
"required": False, "type": "dict", "required": False, "type": "dict", "default": None,
"options": { "options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"id": {"required": True, "type": "int"} "id": {"required": True, "type": "int"}
} }
@ -243,15 +275,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_ips(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_ips(module.params, fos) login(module.params, fos)
is_error, has_changed, result = fortios_ips(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)

@ -3693,38 +3693,6 @@ lib/ansible/modules/network/fortios/fortios_firewall_DoS_policy.py validate-modu
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_sniffer.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_firewall_sniffer.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_ttl_policy.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vip.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_vip.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vip46.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_vip46.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vip6.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_vip6.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vip64.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_vip64.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vipgrp.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vipgrp46.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vipgrp6.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_vipgrp64.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_wildcard_fqdn_custom.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_firewall_wildcard_fqdn_custom.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_firewall_wildcard_fqdn_group.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ftp_proxy_explicit.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_ftp_proxy_explicit.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_icap_profile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_icap_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_icap_server.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_icap_server.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_custom.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_ips_custom.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_decoder.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_global.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_ips_global.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_rule.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_ips_rule.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_rule_settings.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_sensor.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_ips_sensor.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_ips_sensor.py validate-modules:E337 lib/ansible/modules/network/fortios/fortios_ips_sensor.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ips_settings.py validate-modules:E336 lib/ansible/modules/network/fortios/fortios_ips_settings.py validate-modules:E336

@ -0,0 +1,309 @@
# 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_ssh_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_ssl_ssh_profile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ssl_ssh_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_ssl_ssh_profile': {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi_over_https': 'enable',
'name': 'default_name_6',
'rpc_over_https': 'enable',
'server_cert': 'test_value_8',
'server_cert_mode': 're-sign',
'ssl_anomalies_log': 'disable',
'ssl_exemptions_log': 'disable',
'untrusted_caname': 'test_value_12',
'use_ssl_server': 'disable',
'whitelist': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_ssh_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi-over-https': 'enable',
'name': 'default_name_6',
'rpc-over-https': 'enable',
'server-cert': 'test_value_8',
'server-cert-mode': 're-sign',
'ssl-anomalies-log': 'disable',
'ssl-exemptions-log': 'disable',
'untrusted-caname': 'test_value_12',
'use-ssl-server': 'disable',
'whitelist': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-ssh-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_ssl_ssh_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_ssl_ssh_profile': {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi_over_https': 'enable',
'name': 'default_name_6',
'rpc_over_https': 'enable',
'server_cert': 'test_value_8',
'server_cert_mode': 're-sign',
'ssl_anomalies_log': 'disable',
'ssl_exemptions_log': 'disable',
'untrusted_caname': 'test_value_12',
'use_ssl_server': 'disable',
'whitelist': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_ssh_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi-over-https': 'enable',
'name': 'default_name_6',
'rpc-over-https': 'enable',
'server-cert': 'test_value_8',
'server-cert-mode': 're-sign',
'ssl-anomalies-log': 'disable',
'ssl-exemptions-log': 'disable',
'untrusted-caname': 'test_value_12',
'use-ssl-server': 'disable',
'whitelist': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-ssh-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_ssl_ssh_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_ssl_ssh_profile': {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi_over_https': 'enable',
'name': 'default_name_6',
'rpc_over_https': 'enable',
'server_cert': 'test_value_8',
'server_cert_mode': 're-sign',
'ssl_anomalies_log': 'disable',
'ssl_exemptions_log': 'disable',
'untrusted_caname': 'test_value_12',
'use_ssl_server': 'disable',
'whitelist': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_ssh_profile.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'ssl-ssh-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_ssl_ssh_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_ssl_ssh_profile': {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi_over_https': 'enable',
'name': 'default_name_6',
'rpc_over_https': 'enable',
'server_cert': 'test_value_8',
'server_cert_mode': 're-sign',
'ssl_anomalies_log': 'disable',
'ssl_exemptions_log': 'disable',
'untrusted_caname': 'test_value_12',
'use_ssl_server': 'disable',
'whitelist': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_ssh_profile.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'ssl-ssh-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_ssl_ssh_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_ssl_ssh_profile': {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi_over_https': 'enable',
'name': 'default_name_6',
'rpc_over_https': 'enable',
'server_cert': 'test_value_8',
'server_cert_mode': 're-sign',
'ssl_anomalies_log': 'disable',
'ssl_exemptions_log': 'disable',
'untrusted_caname': 'test_value_12',
'use_ssl_server': 'disable',
'whitelist': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_ssh_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi-over-https': 'enable',
'name': 'default_name_6',
'rpc-over-https': 'enable',
'server-cert': 'test_value_8',
'server-cert-mode': 're-sign',
'ssl-anomalies-log': 'disable',
'ssl-exemptions-log': 'disable',
'untrusted-caname': 'test_value_12',
'use-ssl-server': 'disable',
'whitelist': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-ssh-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_ssl_ssh_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_ssl_ssh_profile': {
'random_attribute_not_valid': 'tag',
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi_over_https': 'enable',
'name': 'default_name_6',
'rpc_over_https': 'enable',
'server_cert': 'test_value_8',
'server_cert_mode': 're-sign',
'ssl_anomalies_log': 'disable',
'ssl_exemptions_log': 'disable',
'untrusted_caname': 'test_value_12',
'use_ssl_server': 'disable',
'whitelist': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ssl_ssh_profile.fortios_firewall(input_data, fos_instance)
expected_data = {
'caname': 'test_value_3',
'comment': 'Optional comments.',
'mapi-over-https': 'enable',
'name': 'default_name_6',
'rpc-over-https': 'enable',
'server-cert': 'test_value_8',
'server-cert-mode': 're-sign',
'ssl-anomalies-log': 'disable',
'ssl-exemptions-log': 'disable',
'untrusted-caname': 'test_value_12',
'use-ssl-server': 'disable',
'whitelist': 'enable'
}
set_method_mock.assert_called_with('firewall', 'ssl-ssh-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,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_ttl_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_ttl_policy.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_ttl_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_ttl_policy': {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ttl_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
}
set_method_mock.assert_called_with('firewall', 'ttl-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_ttl_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_ttl_policy': {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ttl_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
}
set_method_mock.assert_called_with('firewall', 'ttl-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_ttl_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_ttl_policy': {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ttl_policy.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'ttl-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_ttl_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_ttl_policy': {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ttl_policy.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'ttl-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_ttl_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_ttl_policy': {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ttl_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
}
set_method_mock.assert_called_with('firewall', 'ttl-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_ttl_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_ttl_policy': {
'random_attribute_not_valid': 'tag',
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_ttl_policy.fortios_firewall(input_data, fos_instance)
expected_data = {
'action': 'accept',
'id': '4',
'schedule': 'test_value_5',
'srcintf': 'test_value_6',
'status': 'enable',
'ttl': 'test_value_8'
}
set_method_mock.assert_called_with('firewall', 'ttl-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,839 @@
# 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_vip
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_vip.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vip_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_vip': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns_mapping_ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous_arp_interval': '10',
'http_cookie_age': '11',
'http_cookie_domain': 'test_value_12',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '14',
'http_cookie_path': 'test_value_15',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_18',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '21',
'ldb_method': 'static',
'mapped_addr': 'test_value_23',
'mappedport': 'test_value_24',
'max_embryonic_connections': '25',
'name': 'default_name_26',
'nat_source_vip': 'disable',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping_type': '1-to-1',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_35',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '38',
'ssl_client_session_state_timeout': '39',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '43',
'ssl_hpkp_backup': 'test_value_44',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_46',
'ssl_hpkp_report_uri': 'test_value_47',
'ssl_hsts': 'disable',
'ssl_hsts_age': '49',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '61',
'ssl_server_session_state_timeout': '62',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns-mapping-ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous-arp-interval': '10',
'http-cookie-age': '11',
'http-cookie-domain': 'test_value_12',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '14',
'http-cookie-path': 'test_value_15',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_18',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '21',
'ldb-method': 'static',
'mapped-addr': 'test_value_23',
'mappedport': 'test_value_24',
'max-embryonic-connections': '25',
'name': 'default_name_26',
'nat-source-vip': 'disable',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping-type': '1-to-1',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_35',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '38',
'ssl-client-session-state-timeout': '39',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '43',
'ssl-hpkp-backup': 'test_value_44',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_46',
'ssl-hpkp-report-uri': 'test_value_47',
'ssl-hsts': 'disable',
'ssl-hsts-age': '49',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '61',
'ssl-server-session-state-timeout': '62',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip', 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_vip_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_vip': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns_mapping_ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous_arp_interval': '10',
'http_cookie_age': '11',
'http_cookie_domain': 'test_value_12',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '14',
'http_cookie_path': 'test_value_15',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_18',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '21',
'ldb_method': 'static',
'mapped_addr': 'test_value_23',
'mappedport': 'test_value_24',
'max_embryonic_connections': '25',
'name': 'default_name_26',
'nat_source_vip': 'disable',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping_type': '1-to-1',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_35',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '38',
'ssl_client_session_state_timeout': '39',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '43',
'ssl_hpkp_backup': 'test_value_44',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_46',
'ssl_hpkp_report_uri': 'test_value_47',
'ssl_hsts': 'disable',
'ssl_hsts_age': '49',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '61',
'ssl_server_session_state_timeout': '62',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns-mapping-ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous-arp-interval': '10',
'http-cookie-age': '11',
'http-cookie-domain': 'test_value_12',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '14',
'http-cookie-path': 'test_value_15',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_18',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '21',
'ldb-method': 'static',
'mapped-addr': 'test_value_23',
'mappedport': 'test_value_24',
'max-embryonic-connections': '25',
'name': 'default_name_26',
'nat-source-vip': 'disable',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping-type': '1-to-1',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_35',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '38',
'ssl-client-session-state-timeout': '39',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '43',
'ssl-hpkp-backup': 'test_value_44',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_46',
'ssl-hpkp-report-uri': 'test_value_47',
'ssl-hsts': 'disable',
'ssl-hsts-age': '49',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '61',
'ssl-server-session-state-timeout': '62',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip', 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_vip_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_vip': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns_mapping_ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous_arp_interval': '10',
'http_cookie_age': '11',
'http_cookie_domain': 'test_value_12',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '14',
'http_cookie_path': 'test_value_15',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_18',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '21',
'ldb_method': 'static',
'mapped_addr': 'test_value_23',
'mappedport': 'test_value_24',
'max_embryonic_connections': '25',
'name': 'default_name_26',
'nat_source_vip': 'disable',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping_type': '1-to-1',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_35',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '38',
'ssl_client_session_state_timeout': '39',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '43',
'ssl_hpkp_backup': 'test_value_44',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_46',
'ssl_hpkp_report_uri': 'test_value_47',
'ssl_hsts': 'disable',
'ssl_hsts_age': '49',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '61',
'ssl_server_session_state_timeout': '62',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip', 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_vip_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_vip': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns_mapping_ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous_arp_interval': '10',
'http_cookie_age': '11',
'http_cookie_domain': 'test_value_12',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '14',
'http_cookie_path': 'test_value_15',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_18',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '21',
'ldb_method': 'static',
'mapped_addr': 'test_value_23',
'mappedport': 'test_value_24',
'max_embryonic_connections': '25',
'name': 'default_name_26',
'nat_source_vip': 'disable',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping_type': '1-to-1',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_35',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '38',
'ssl_client_session_state_timeout': '39',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '43',
'ssl_hpkp_backup': 'test_value_44',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_46',
'ssl_hpkp_report_uri': 'test_value_47',
'ssl_hsts': 'disable',
'ssl_hsts_age': '49',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '61',
'ssl_server_session_state_timeout': '62',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip', 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_vip_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_vip': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns_mapping_ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous_arp_interval': '10',
'http_cookie_age': '11',
'http_cookie_domain': 'test_value_12',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '14',
'http_cookie_path': 'test_value_15',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_18',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '21',
'ldb_method': 'static',
'mapped_addr': 'test_value_23',
'mappedport': 'test_value_24',
'max_embryonic_connections': '25',
'name': 'default_name_26',
'nat_source_vip': 'disable',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping_type': '1-to-1',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_35',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '38',
'ssl_client_session_state_timeout': '39',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '43',
'ssl_hpkp_backup': 'test_value_44',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_46',
'ssl_hpkp_report_uri': 'test_value_47',
'ssl_hsts': 'disable',
'ssl_hsts_age': '49',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '61',
'ssl_server_session_state_timeout': '62',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns-mapping-ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous-arp-interval': '10',
'http-cookie-age': '11',
'http-cookie-domain': 'test_value_12',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '14',
'http-cookie-path': 'test_value_15',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_18',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '21',
'ldb-method': 'static',
'mapped-addr': 'test_value_23',
'mappedport': 'test_value_24',
'max-embryonic-connections': '25',
'name': 'default_name_26',
'nat-source-vip': 'disable',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping-type': '1-to-1',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_35',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '38',
'ssl-client-session-state-timeout': '39',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '43',
'ssl-hpkp-backup': 'test_value_44',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_46',
'ssl-hpkp-report-uri': 'test_value_47',
'ssl-hsts': 'disable',
'ssl-hsts-age': '49',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '61',
'ssl-server-session-state-timeout': '62',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip', 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_vip_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_vip': {
'random_attribute_not_valid': 'tag',
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns_mapping_ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous_arp_interval': '10',
'http_cookie_age': '11',
'http_cookie_domain': 'test_value_12',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '14',
'http_cookie_path': 'test_value_15',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_18',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '21',
'ldb_method': 'static',
'mapped_addr': 'test_value_23',
'mappedport': 'test_value_24',
'max_embryonic_connections': '25',
'name': 'default_name_26',
'nat_source_vip': 'disable',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping_type': '1-to-1',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_35',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '38',
'ssl_client_session_state_timeout': '39',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '43',
'ssl_hpkp_backup': 'test_value_44',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_46',
'ssl_hpkp_report_uri': 'test_value_47',
'ssl_hsts': 'disable',
'ssl_hsts_age': '49',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '61',
'ssl_server_session_state_timeout': '62',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'dns-mapping-ttl': '6',
'extintf': 'test_value_7',
'extip': 'test_value_8',
'extport': 'test_value_9',
'gratuitous-arp-interval': '10',
'http-cookie-age': '11',
'http-cookie-domain': 'test_value_12',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '14',
'http-cookie-path': 'test_value_15',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_18',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '21',
'ldb-method': 'static',
'mapped-addr': 'test_value_23',
'mappedport': 'test_value_24',
'max-embryonic-connections': '25',
'name': 'default_name_26',
'nat-source-vip': 'disable',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'portmapping-type': '1-to-1',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_35',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '38',
'ssl-client-session-state-timeout': '39',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '43',
'ssl-hpkp-backup': 'test_value_44',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_46',
'ssl-hpkp-report-uri': 'test_value_47',
'ssl-hsts': 'disable',
'ssl-hsts-age': '49',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '61',
'ssl-server-session-state-timeout': '62',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_65',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip', 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,339 @@
# 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_vip46
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_vip46.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vip46_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_vip46': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip46', 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_vip46_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_vip46': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip46', 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_vip46_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_vip46': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip46', 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_vip46_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_vip46': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip46', 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_vip46_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_vip46': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip46', 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_vip46_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_vip46': {
'random_attribute_not_valid': 'tag',
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip46.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip46', 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,789 @@
# 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_vip6
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_vip6.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vip6_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_vip6': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http_cookie_age': '8',
'http_cookie_domain': 'test_value_9',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '11',
'http_cookie_path': 'test_value_12',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_15',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '18',
'ldb_method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max_embryonic_connections': '22',
'name': 'default_name_23',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_30',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '33',
'ssl_client_session_state_timeout': '34',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '38',
'ssl_hpkp_backup': 'test_value_39',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_41',
'ssl_hpkp_report_uri': 'test_value_42',
'ssl_hsts': 'disable',
'ssl_hsts_age': '44',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '56',
'ssl_server_session_state_timeout': '57',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip6.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http-cookie-age': '8',
'http-cookie-domain': 'test_value_9',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '11',
'http-cookie-path': 'test_value_12',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_15',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '18',
'ldb-method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max-embryonic-connections': '22',
'name': 'default_name_23',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_30',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '33',
'ssl-client-session-state-timeout': '34',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '38',
'ssl-hpkp-backup': 'test_value_39',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_41',
'ssl-hpkp-report-uri': 'test_value_42',
'ssl-hsts': 'disable',
'ssl-hsts-age': '44',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '56',
'ssl-server-session-state-timeout': '57',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip6', 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_vip6_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_vip6': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http_cookie_age': '8',
'http_cookie_domain': 'test_value_9',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '11',
'http_cookie_path': 'test_value_12',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_15',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '18',
'ldb_method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max_embryonic_connections': '22',
'name': 'default_name_23',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_30',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '33',
'ssl_client_session_state_timeout': '34',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '38',
'ssl_hpkp_backup': 'test_value_39',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_41',
'ssl_hpkp_report_uri': 'test_value_42',
'ssl_hsts': 'disable',
'ssl_hsts_age': '44',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '56',
'ssl_server_session_state_timeout': '57',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip6.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http-cookie-age': '8',
'http-cookie-domain': 'test_value_9',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '11',
'http-cookie-path': 'test_value_12',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_15',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '18',
'ldb-method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max-embryonic-connections': '22',
'name': 'default_name_23',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_30',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '33',
'ssl-client-session-state-timeout': '34',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '38',
'ssl-hpkp-backup': 'test_value_39',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_41',
'ssl-hpkp-report-uri': 'test_value_42',
'ssl-hsts': 'disable',
'ssl-hsts-age': '44',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '56',
'ssl-server-session-state-timeout': '57',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip6', 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_vip6_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_vip6': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http_cookie_age': '8',
'http_cookie_domain': 'test_value_9',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '11',
'http_cookie_path': 'test_value_12',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_15',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '18',
'ldb_method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max_embryonic_connections': '22',
'name': 'default_name_23',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_30',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '33',
'ssl_client_session_state_timeout': '34',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '38',
'ssl_hpkp_backup': 'test_value_39',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_41',
'ssl_hpkp_report_uri': 'test_value_42',
'ssl_hsts': 'disable',
'ssl_hsts_age': '44',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '56',
'ssl_server_session_state_timeout': '57',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip6.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip6', 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_vip6_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_vip6': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http_cookie_age': '8',
'http_cookie_domain': 'test_value_9',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '11',
'http_cookie_path': 'test_value_12',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_15',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '18',
'ldb_method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max_embryonic_connections': '22',
'name': 'default_name_23',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_30',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '33',
'ssl_client_session_state_timeout': '34',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '38',
'ssl_hpkp_backup': 'test_value_39',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_41',
'ssl_hpkp_report_uri': 'test_value_42',
'ssl_hsts': 'disable',
'ssl_hsts_age': '44',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '56',
'ssl_server_session_state_timeout': '57',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip6.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip6', 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_vip6_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_vip6': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http_cookie_age': '8',
'http_cookie_domain': 'test_value_9',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '11',
'http_cookie_path': 'test_value_12',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_15',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '18',
'ldb_method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max_embryonic_connections': '22',
'name': 'default_name_23',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_30',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '33',
'ssl_client_session_state_timeout': '34',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '38',
'ssl_hpkp_backup': 'test_value_39',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_41',
'ssl_hpkp_report_uri': 'test_value_42',
'ssl_hsts': 'disable',
'ssl_hsts_age': '44',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '56',
'ssl_server_session_state_timeout': '57',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip6.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http-cookie-age': '8',
'http-cookie-domain': 'test_value_9',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '11',
'http-cookie-path': 'test_value_12',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_15',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '18',
'ldb-method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max-embryonic-connections': '22',
'name': 'default_name_23',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_30',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '33',
'ssl-client-session-state-timeout': '34',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '38',
'ssl-hpkp-backup': 'test_value_39',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_41',
'ssl-hpkp-report-uri': 'test_value_42',
'ssl-hsts': 'disable',
'ssl-hsts-age': '44',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '56',
'ssl-server-session-state-timeout': '57',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip6', 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_vip6_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_vip6': {
'random_attribute_not_valid': 'tag',
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http_cookie_age': '8',
'http_cookie_domain': 'test_value_9',
'http_cookie_domain_from_host': 'disable',
'http_cookie_generation': '11',
'http_cookie_path': 'test_value_12',
'http_cookie_share': 'disable',
'http_ip_header': 'enable',
'http_ip_header_name': 'test_value_15',
'http_multiplex': 'enable',
'https_cookie_secure': 'disable',
'id': '18',
'ldb_method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max_embryonic_connections': '22',
'name': 'default_name_23',
'outlook_web_access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'ssl_algorithm': 'high',
'ssl_certificate': 'test_value_30',
'ssl_client_fallback': 'disable',
'ssl_client_renegotiation': 'allow',
'ssl_client_session_state_max': '33',
'ssl_client_session_state_timeout': '34',
'ssl_client_session_state_type': 'disable',
'ssl_dh_bits': '768',
'ssl_hpkp': 'disable',
'ssl_hpkp_age': '38',
'ssl_hpkp_backup': 'test_value_39',
'ssl_hpkp_include_subdomains': 'disable',
'ssl_hpkp_primary': 'test_value_41',
'ssl_hpkp_report_uri': 'test_value_42',
'ssl_hsts': 'disable',
'ssl_hsts_age': '44',
'ssl_hsts_include_subdomains': 'disable',
'ssl_http_location_conversion': 'enable',
'ssl_http_match_host': 'enable',
'ssl_max_version': 'ssl-3.0',
'ssl_min_version': 'ssl-3.0',
'ssl_mode': 'half',
'ssl_pfs': 'require',
'ssl_send_empty_frags': 'enable',
'ssl_server_algorithm': 'high',
'ssl_server_max_version': 'ssl-3.0',
'ssl_server_min_version': 'ssl-3.0',
'ssl_server_session_state_max': '56',
'ssl_server_session_state_timeout': '57',
'ssl_server_session_state_type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic_server': 'disable',
'websphere_server': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip6.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'http-cookie-age': '8',
'http-cookie-domain': 'test_value_9',
'http-cookie-domain-from-host': 'disable',
'http-cookie-generation': '11',
'http-cookie-path': 'test_value_12',
'http-cookie-share': 'disable',
'http-ip-header': 'enable',
'http-ip-header-name': 'test_value_15',
'http-multiplex': 'enable',
'https-cookie-secure': 'disable',
'id': '18',
'ldb-method': 'static',
'mappedip': 'test_value_20',
'mappedport': 'test_value_21',
'max-embryonic-connections': '22',
'name': 'default_name_23',
'outlook-web-access': 'disable',
'persistence': 'none',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'ssl-algorithm': 'high',
'ssl-certificate': 'test_value_30',
'ssl-client-fallback': 'disable',
'ssl-client-renegotiation': 'allow',
'ssl-client-session-state-max': '33',
'ssl-client-session-state-timeout': '34',
'ssl-client-session-state-type': 'disable',
'ssl-dh-bits': '768',
'ssl-hpkp': 'disable',
'ssl-hpkp-age': '38',
'ssl-hpkp-backup': 'test_value_39',
'ssl-hpkp-include-subdomains': 'disable',
'ssl-hpkp-primary': 'test_value_41',
'ssl-hpkp-report-uri': 'test_value_42',
'ssl-hsts': 'disable',
'ssl-hsts-age': '44',
'ssl-hsts-include-subdomains': 'disable',
'ssl-http-location-conversion': 'enable',
'ssl-http-match-host': 'enable',
'ssl-max-version': 'ssl-3.0',
'ssl-min-version': 'ssl-3.0',
'ssl-mode': 'half',
'ssl-pfs': 'require',
'ssl-send-empty-frags': 'enable',
'ssl-server-algorithm': 'high',
'ssl-server-max-version': 'ssl-3.0',
'ssl-server-min-version': 'ssl-3.0',
'ssl-server-session-state-max': '56',
'ssl-server-session-state-timeout': '57',
'ssl-server-session-state-type': 'disable',
'type': 'static-nat',
'uuid': 'test_value_60',
'weblogic-server': 'disable',
'websphere-server': 'disable'
}
set_method_mock.assert_called_with('firewall', 'vip6', 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,339 @@
# 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_vip64
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_vip64.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vip64_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_vip64': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip64.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip64', 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_vip64_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_vip64': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip64.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip64', 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_vip64_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_vip64': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip64.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip64', 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_vip64_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_vip64': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip64.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vip64', 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_vip64_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_vip64': {
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip64.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip64', 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_vip64_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_vip64': {
'random_attribute_not_valid': 'tag',
'arp_reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb_method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server_type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vip64.fortios_firewall(input_data, fos_instance)
expected_data = {
'arp-reply': 'disable',
'color': '4',
'comment': 'Comment.',
'extip': 'test_value_6',
'extport': 'test_value_7',
'id': '8',
'ldb-method': 'static',
'mappedip': 'test_value_10',
'mappedport': 'test_value_11',
'name': 'default_name_12',
'portforward': 'disable',
'protocol': 'tcp',
'server-type': 'http',
'type': 'static-nat',
'uuid': 'test_value_17'
}
set_method_mock.assert_called_with('firewall', 'vip64', 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_vipgrp
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_vipgrp.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vipgrp_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_vipgrp': {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
}
set_method_mock.assert_called_with('firewall', 'vipgrp', 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_vipgrp_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_vipgrp': {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
}
set_method_mock.assert_called_with('firewall', 'vipgrp', 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_vipgrp_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_vipgrp': {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp', 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_vipgrp_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_vipgrp': {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp', 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_vipgrp_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_vipgrp': {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
}
set_method_mock.assert_called_with('firewall', 'vipgrp', 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_vipgrp_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_vipgrp': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'interface': 'test_value_5',
'name': 'default_name_6',
'uuid': 'test_value_7'
}
set_method_mock.assert_called_with('firewall', 'vipgrp', 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_vipgrp46
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_vipgrp46.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vipgrp46_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_vipgrp46': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp46.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp46', 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_vipgrp46_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_vipgrp46': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp46.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp46', 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_vipgrp46_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_vipgrp46': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp46.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp46', 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_vipgrp46_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_vipgrp46': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp46.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp46', 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_vipgrp46_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_vipgrp46': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp46.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp46', 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_vipgrp46_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_vipgrp46': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp46.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp46', 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_vipgrp6
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_vipgrp6.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vipgrp6_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_vipgrp6': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp6.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp6', 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_vipgrp6_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_vipgrp6': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp6.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp6', 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_vipgrp6_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_vipgrp6': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp6.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp6', 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_vipgrp6_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_vipgrp6': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp6.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp6', 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_vipgrp6_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_vipgrp6': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp6.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp6', 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_vipgrp6_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_vipgrp6': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp6.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp6', 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_vipgrp64
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_vipgrp64.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_vipgrp64_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_vipgrp64': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp64.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp64', 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_vipgrp64_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_vipgrp64': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp64.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp64', 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_vipgrp64_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_vipgrp64': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp64.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp64', 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_vipgrp64_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_vipgrp64': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp64.fortios_firewall(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall', 'vipgrp64', 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_vipgrp64_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_vipgrp64': {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp64.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp64', 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_vipgrp64_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_vipgrp64': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_vipgrp64.fortios_firewall(input_data, fos_instance)
expected_data = {
'color': '3',
'comments': 'test_value_4',
'name': 'default_name_5',
'uuid': 'test_value_6'
}
set_method_mock.assert_called_with('firewall', 'vipgrp64', 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_wildcard_fqdn_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_wildcard_fqdn_custom.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_wildcard_fqdn_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_wildcard_fqdn_custom': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard_fqdn': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_custom.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard-fqdn': 'test_value_8'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_custom': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard_fqdn': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_custom.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard-fqdn': 'test_value_8'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_custom': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard_fqdn': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_custom.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_custom': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard_fqdn': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_custom.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_custom': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard_fqdn': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_custom.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard-fqdn': 'test_value_8'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_custom': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard_fqdn': 'test_value_8'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_custom.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable',
'wildcard-fqdn': 'test_value_8'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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,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_wildcard_fqdn_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_wildcard_fqdn_group.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_firewall_wildcard_fqdn_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_wildcard_fqdn_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_group.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_group.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_group.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_group.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
delete_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_group': {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_group.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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_wildcard_fqdn_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_wildcard_fqdn_group': {
'random_attribute_not_valid': 'tag',
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_firewall_wildcard_fqdn_group.fortios_firewall_wildcard_fqdn(input_data, fos_instance)
expected_data = {
'color': '3',
'comment': 'Comment.',
'name': 'default_name_5',
'uuid': 'test_value_6',
'visibility': 'enable'
}
set_method_mock.assert_called_with('firewall.wildcard-fqdn', '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,183 @@
# 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_ftp_proxy_explicit
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_ftp_proxy_explicit.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ftp_proxy_explicit_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',
'ftp_proxy_explicit': {
'incoming_ip': 'test_value_3',
'incoming_port': 'test_value_4',
'outgoing_ip': 'test_value_5',
'sec_default_action': 'accept',
'status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ftp_proxy_explicit.fortios_ftp_proxy(input_data, fos_instance)
expected_data = {
'incoming-ip': 'test_value_3',
'incoming-port': 'test_value_4',
'outgoing-ip': 'test_value_5',
'sec-default-action': 'accept',
'status': 'enable'
}
set_method_mock.assert_called_with('ftp-proxy', 'explicit', 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_ftp_proxy_explicit_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',
'ftp_proxy_explicit': {
'incoming_ip': 'test_value_3',
'incoming_port': 'test_value_4',
'outgoing_ip': 'test_value_5',
'sec_default_action': 'accept',
'status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ftp_proxy_explicit.fortios_ftp_proxy(input_data, fos_instance)
expected_data = {
'incoming-ip': 'test_value_3',
'incoming-port': 'test_value_4',
'outgoing-ip': 'test_value_5',
'sec-default-action': 'accept',
'status': 'enable'
}
set_method_mock.assert_called_with('ftp-proxy', 'explicit', 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_ftp_proxy_explicit_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',
'ftp_proxy_explicit': {
'incoming_ip': 'test_value_3',
'incoming_port': 'test_value_4',
'outgoing_ip': 'test_value_5',
'sec_default_action': 'accept',
'status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ftp_proxy_explicit.fortios_ftp_proxy(input_data, fos_instance)
expected_data = {
'incoming-ip': 'test_value_3',
'incoming-port': 'test_value_4',
'outgoing-ip': 'test_value_5',
'sec-default-action': 'accept',
'status': 'enable'
}
set_method_mock.assert_called_with('ftp-proxy', 'explicit', 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_ftp_proxy_explicit_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',
'ftp_proxy_explicit': {
'random_attribute_not_valid': 'tag',
'incoming_ip': 'test_value_3',
'incoming_port': 'test_value_4',
'outgoing_ip': 'test_value_5',
'sec_default_action': 'accept',
'status': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ftp_proxy_explicit.fortios_ftp_proxy(input_data, fos_instance)
expected_data = {
'incoming-ip': 'test_value_3',
'incoming-port': 'test_value_4',
'outgoing-ip': 'test_value_5',
'sec-default-action': 'accept',
'status': 'enable'
}
set_method_mock.assert_called_with('ftp-proxy', 'explicit', 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,309 @@
# 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_icap_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_icap_profile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_icap_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',
'icap_profile': {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg_group': 'test_value_5',
'request': 'disable',
'request_failure': 'error',
'request_path': 'test_value_8',
'request_server': 'test_value_9',
'response': 'disable',
'response_failure': 'error',
'response_path': 'test_value_12',
'response_server': 'test_value_13',
'streaming_content_bypass': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_profile.fortios_icap(input_data, fos_instance)
expected_data = {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg-group': 'test_value_5',
'request': 'disable',
'request-failure': 'error',
'request-path': 'test_value_8',
'request-server': 'test_value_9',
'response': 'disable',
'response-failure': 'error',
'response-path': 'test_value_12',
'response-server': 'test_value_13',
'streaming-content-bypass': 'disable'
}
set_method_mock.assert_called_with('icap', '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_icap_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',
'icap_profile': {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg_group': 'test_value_5',
'request': 'disable',
'request_failure': 'error',
'request_path': 'test_value_8',
'request_server': 'test_value_9',
'response': 'disable',
'response_failure': 'error',
'response_path': 'test_value_12',
'response_server': 'test_value_13',
'streaming_content_bypass': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_profile.fortios_icap(input_data, fos_instance)
expected_data = {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg-group': 'test_value_5',
'request': 'disable',
'request-failure': 'error',
'request-path': 'test_value_8',
'request-server': 'test_value_9',
'response': 'disable',
'response-failure': 'error',
'response-path': 'test_value_12',
'response-server': 'test_value_13',
'streaming-content-bypass': 'disable'
}
set_method_mock.assert_called_with('icap', '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_icap_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',
'icap_profile': {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg_group': 'test_value_5',
'request': 'disable',
'request_failure': 'error',
'request_path': 'test_value_8',
'request_server': 'test_value_9',
'response': 'disable',
'response_failure': 'error',
'response_path': 'test_value_12',
'response_server': 'test_value_13',
'streaming_content_bypass': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_profile.fortios_icap(input_data, fos_instance)
delete_method_mock.assert_called_with('icap', '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_icap_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',
'icap_profile': {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg_group': 'test_value_5',
'request': 'disable',
'request_failure': 'error',
'request_path': 'test_value_8',
'request_server': 'test_value_9',
'response': 'disable',
'response_failure': 'error',
'response_path': 'test_value_12',
'response_server': 'test_value_13',
'streaming_content_bypass': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_profile.fortios_icap(input_data, fos_instance)
delete_method_mock.assert_called_with('icap', '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_icap_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',
'icap_profile': {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg_group': 'test_value_5',
'request': 'disable',
'request_failure': 'error',
'request_path': 'test_value_8',
'request_server': 'test_value_9',
'response': 'disable',
'response_failure': 'error',
'response_path': 'test_value_12',
'response_server': 'test_value_13',
'streaming_content_bypass': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_profile.fortios_icap(input_data, fos_instance)
expected_data = {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg-group': 'test_value_5',
'request': 'disable',
'request-failure': 'error',
'request-path': 'test_value_8',
'request-server': 'test_value_9',
'response': 'disable',
'response-failure': 'error',
'response-path': 'test_value_12',
'response-server': 'test_value_13',
'streaming-content-bypass': 'disable'
}
set_method_mock.assert_called_with('icap', '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_icap_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',
'icap_profile': {
'random_attribute_not_valid': 'tag',
'methods': 'delete',
'name': 'default_name_4',
'replacemsg_group': 'test_value_5',
'request': 'disable',
'request_failure': 'error',
'request_path': 'test_value_8',
'request_server': 'test_value_9',
'response': 'disable',
'response_failure': 'error',
'response_path': 'test_value_12',
'response_server': 'test_value_13',
'streaming_content_bypass': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_profile.fortios_icap(input_data, fos_instance)
expected_data = {
'methods': 'delete',
'name': 'default_name_4',
'replacemsg-group': 'test_value_5',
'request': 'disable',
'request-failure': 'error',
'request-path': 'test_value_8',
'request-server': 'test_value_9',
'response': 'disable',
'response-failure': 'error',
'response-path': 'test_value_12',
'response-server': 'test_value_13',
'streaming-content-bypass': 'disable'
}
set_method_mock.assert_called_with('icap', '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,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_icap_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_icap_server.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_icap_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',
'icap_server': {
'ip_address': 'test_value_3',
'ip_version': '4',
'ip6_address': 'test_value_5',
'max_connections': '6',
'name': 'default_name_7',
'port': '8'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_server.fortios_icap(input_data, fos_instance)
expected_data = {
'ip-address': 'test_value_3',
'ip-version': '4',
'ip6-address': 'test_value_5',
'max-connections': '6',
'name': 'default_name_7',
'port': '8'
}
set_method_mock.assert_called_with('icap', '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_icap_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',
'icap_server': {
'ip_address': 'test_value_3',
'ip_version': '4',
'ip6_address': 'test_value_5',
'max_connections': '6',
'name': 'default_name_7',
'port': '8'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_server.fortios_icap(input_data, fos_instance)
expected_data = {
'ip-address': 'test_value_3',
'ip-version': '4',
'ip6-address': 'test_value_5',
'max-connections': '6',
'name': 'default_name_7',
'port': '8'
}
set_method_mock.assert_called_with('icap', '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_icap_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',
'icap_server': {
'ip_address': 'test_value_3',
'ip_version': '4',
'ip6_address': 'test_value_5',
'max_connections': '6',
'name': 'default_name_7',
'port': '8'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_server.fortios_icap(input_data, fos_instance)
delete_method_mock.assert_called_with('icap', '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_icap_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',
'icap_server': {
'ip_address': 'test_value_3',
'ip_version': '4',
'ip6_address': 'test_value_5',
'max_connections': '6',
'name': 'default_name_7',
'port': '8'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_server.fortios_icap(input_data, fos_instance)
delete_method_mock.assert_called_with('icap', '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_icap_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',
'icap_server': {
'ip_address': 'test_value_3',
'ip_version': '4',
'ip6_address': 'test_value_5',
'max_connections': '6',
'name': 'default_name_7',
'port': '8'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_server.fortios_icap(input_data, fos_instance)
expected_data = {
'ip-address': 'test_value_3',
'ip-version': '4',
'ip6-address': 'test_value_5',
'max-connections': '6',
'name': 'default_name_7',
'port': '8'
}
set_method_mock.assert_called_with('icap', '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_icap_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',
'icap_server': {
'random_attribute_not_valid': 'tag',
'ip_address': 'test_value_3',
'ip_version': '4',
'ip6_address': 'test_value_5',
'max_connections': '6',
'name': 'default_name_7',
'port': '8'
},
'vdom': 'root'}
is_error, changed, response = fortios_icap_server.fortios_icap(input_data, fos_instance)
expected_data = {
'ip-address': 'test_value_3',
'ip-version': '4',
'ip6-address': 'test_value_5',
'max-connections': '6',
'name': 'default_name_7',
'port': '8'
}
set_method_mock.assert_called_with('icap', '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,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_ips_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_ips_custom.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ips_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',
'ips_custom': {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log_packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule_id': '11',
'severity': 'test_value_12',
'sig_name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_custom.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log-packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule-id': '11',
'severity': 'test_value_12',
'sig-name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
}
set_method_mock.assert_called_with('ips', '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_ips_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',
'ips_custom': {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log_packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule_id': '11',
'severity': 'test_value_12',
'sig_name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_custom.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log-packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule-id': '11',
'severity': 'test_value_12',
'sig-name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
}
set_method_mock.assert_called_with('ips', '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_ips_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',
'ips_custom': {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log_packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule_id': '11',
'severity': 'test_value_12',
'sig_name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_custom.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', '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_ips_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',
'ips_custom': {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log_packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule_id': '11',
'severity': 'test_value_12',
'sig_name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_custom.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', '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_ips_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',
'ips_custom': {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log_packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule_id': '11',
'severity': 'test_value_12',
'sig_name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_custom.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log-packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule-id': '11',
'severity': 'test_value_12',
'sig-name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
}
set_method_mock.assert_called_with('ips', '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_ips_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',
'ips_custom': {
'random_attribute_not_valid': 'tag',
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log_packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule_id': '11',
'severity': 'test_value_12',
'sig_name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_custom.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'comment': 'Comment.',
'location': 'test_value_6',
'log': 'disable',
'log-packet': 'disable',
'os': 'test_value_9',
'protocol': 'test_value_10',
'rule-id': '11',
'severity': 'test_value_12',
'sig-name': 'test_value_13',
'signature': 'test_value_14',
'status': 'disable',
'tag': 'test_value_16'
}
set_method_mock.assert_called_with('ips', '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,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_ips_decoder
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_ips_decoder.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ips_decoder_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',
'ips_decoder': {
'name': 'default_name_3',
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_decoder.fortios_ips(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
}
set_method_mock.assert_called_with('ips', 'decoder', 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_ips_decoder_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',
'ips_decoder': {
'name': 'default_name_3',
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_decoder.fortios_ips(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
}
set_method_mock.assert_called_with('ips', 'decoder', 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_ips_decoder_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',
'ips_decoder': {
'name': 'default_name_3',
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_decoder.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', 'decoder', 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_ips_decoder_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',
'ips_decoder': {
'name': 'default_name_3',
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_decoder.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', 'decoder', 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_ips_decoder_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',
'ips_decoder': {
'name': 'default_name_3',
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_decoder.fortios_ips(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
}
set_method_mock.assert_called_with('ips', 'decoder', 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_ips_decoder_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',
'ips_decoder': {
'random_attribute_not_valid': 'tag',
'name': 'default_name_3',
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_decoder.fortios_ips(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
}
set_method_mock.assert_called_with('ips', 'decoder', 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,247 @@
# 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_ips_global
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_ips_global.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ips_global_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',
'ips_global': {
'anomaly_mode': 'periodical',
'database': 'regular',
'deep_app_insp_db_limit': '5',
'deep_app_insp_timeout': '6',
'engine_count': '7',
'exclude_signatures': 'none',
'fail_open': 'enable',
'intelligent_mode': 'enable',
'session_limit_mode': 'accurate',
'skype_client_public_ipaddr': 'test_value_12',
'socket_size': '13',
'sync_session_ttl': 'enable',
'traffic_submit': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_global.fortios_ips(input_data, fos_instance)
expected_data = {
'anomaly-mode': 'periodical',
'database': 'regular',
'deep-app-insp-db-limit': '5',
'deep-app-insp-timeout': '6',
'engine-count': '7',
'exclude-signatures': 'none',
'fail-open': 'enable',
'intelligent-mode': 'enable',
'session-limit-mode': 'accurate',
'skype-client-public-ipaddr': 'test_value_12',
'socket-size': '13',
'sync-session-ttl': 'enable',
'traffic-submit': 'enable'
}
set_method_mock.assert_called_with('ips', 'global', 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_ips_global_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',
'ips_global': {
'anomaly_mode': 'periodical',
'database': 'regular',
'deep_app_insp_db_limit': '5',
'deep_app_insp_timeout': '6',
'engine_count': '7',
'exclude_signatures': 'none',
'fail_open': 'enable',
'intelligent_mode': 'enable',
'session_limit_mode': 'accurate',
'skype_client_public_ipaddr': 'test_value_12',
'socket_size': '13',
'sync_session_ttl': 'enable',
'traffic_submit': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_global.fortios_ips(input_data, fos_instance)
expected_data = {
'anomaly-mode': 'periodical',
'database': 'regular',
'deep-app-insp-db-limit': '5',
'deep-app-insp-timeout': '6',
'engine-count': '7',
'exclude-signatures': 'none',
'fail-open': 'enable',
'intelligent-mode': 'enable',
'session-limit-mode': 'accurate',
'skype-client-public-ipaddr': 'test_value_12',
'socket-size': '13',
'sync-session-ttl': 'enable',
'traffic-submit': 'enable'
}
set_method_mock.assert_called_with('ips', 'global', 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_ips_global_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',
'ips_global': {
'anomaly_mode': 'periodical',
'database': 'regular',
'deep_app_insp_db_limit': '5',
'deep_app_insp_timeout': '6',
'engine_count': '7',
'exclude_signatures': 'none',
'fail_open': 'enable',
'intelligent_mode': 'enable',
'session_limit_mode': 'accurate',
'skype_client_public_ipaddr': 'test_value_12',
'socket_size': '13',
'sync_session_ttl': 'enable',
'traffic_submit': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_global.fortios_ips(input_data, fos_instance)
expected_data = {
'anomaly-mode': 'periodical',
'database': 'regular',
'deep-app-insp-db-limit': '5',
'deep-app-insp-timeout': '6',
'engine-count': '7',
'exclude-signatures': 'none',
'fail-open': 'enable',
'intelligent-mode': 'enable',
'session-limit-mode': 'accurate',
'skype-client-public-ipaddr': 'test_value_12',
'socket-size': '13',
'sync-session-ttl': 'enable',
'traffic-submit': 'enable'
}
set_method_mock.assert_called_with('ips', 'global', 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_ips_global_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',
'ips_global': {
'random_attribute_not_valid': 'tag',
'anomaly_mode': 'periodical',
'database': 'regular',
'deep_app_insp_db_limit': '5',
'deep_app_insp_timeout': '6',
'engine_count': '7',
'exclude_signatures': 'none',
'fail_open': 'enable',
'intelligent_mode': 'enable',
'session_limit_mode': 'accurate',
'skype_client_public_ipaddr': 'test_value_12',
'socket_size': '13',
'sync_session_ttl': 'enable',
'traffic_submit': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_global.fortios_ips(input_data, fos_instance)
expected_data = {
'anomaly-mode': 'periodical',
'database': 'regular',
'deep-app-insp-db-limit': '5',
'deep-app-insp-timeout': '6',
'engine-count': '7',
'exclude-signatures': 'none',
'fail-open': 'enable',
'intelligent-mode': 'enable',
'session-limit-mode': 'accurate',
'skype-client-public-ipaddr': 'test_value_12',
'socket-size': '13',
'sync-session-ttl': 'enable',
'traffic-submit': 'enable'
}
set_method_mock.assert_called_with('ips', 'global', 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_ips_rule
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_ips_rule.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ips_rule_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',
'ips_rule': {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log_packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule_id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log-packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule-id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
}
set_method_mock.assert_called_with('ips', 'rule', 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_ips_rule_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',
'ips_rule': {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log_packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule_id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log-packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule-id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
}
set_method_mock.assert_called_with('ips', 'rule', 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_ips_rule_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',
'ips_rule': {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log_packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule_id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', 'rule', 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_ips_rule_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',
'ips_rule': {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log_packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule_id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', 'rule', 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_ips_rule_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',
'ips_rule': {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log_packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule_id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log-packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule-id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
}
set_method_mock.assert_called_with('ips', 'rule', 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_ips_rule_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',
'ips_rule': {
'random_attribute_not_valid': 'tag',
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log_packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule_id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule.fortios_ips(input_data, fos_instance)
expected_data = {
'action': 'pass',
'application': 'test_value_4',
'date': '5',
'group': 'test_value_6',
'location': 'test_value_7,',
'log': 'disable',
'log-packet': 'disable',
'name': 'default_name_10',
'os': 'test_value_11',
'rev': '12',
'rule-id': '13',
'service': 'test_value_14',
'severity': 'test_value_15,',
'status': 'disable'
}
set_method_mock.assert_called_with('ips', 'rule', 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,199 @@
# 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_ips_rule_settings
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_ips_rule_settings.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ips_rule_settings_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',
'ips_rule_settings': {
'id': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule_settings.fortios_ips(input_data, fos_instance)
expected_data = {
'id': '3'
}
set_method_mock.assert_called_with('ips', 'rule-settings', 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_ips_rule_settings_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',
'ips_rule_settings': {
'id': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule_settings.fortios_ips(input_data, fos_instance)
expected_data = {
'id': '3'
}
set_method_mock.assert_called_with('ips', 'rule-settings', 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_ips_rule_settings_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',
'ips_rule_settings': {
'id': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule_settings.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', 'rule-settings', 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_ips_rule_settings_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',
'ips_rule_settings': {
'id': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule_settings.fortios_ips(input_data, fos_instance)
delete_method_mock.assert_called_with('ips', 'rule-settings', 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_ips_rule_settings_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',
'ips_rule_settings': {
'id': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule_settings.fortios_ips(input_data, fos_instance)
expected_data = {
'id': '3'
}
set_method_mock.assert_called_with('ips', 'rule-settings', 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_ips_rule_settings_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',
'ips_rule_settings': {
'random_attribute_not_valid': 'tag',
'id': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_ips_rule_settings.fortios_ips(input_data, fos_instance)
expected_data = {
'id': '3'
}
set_method_mock.assert_called_with('ips', 'rule-settings', 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