FortiManager Plugin Module Conversion: fmgr_fwobj_address (#52773)

* Auto Commit for: fmgr_fwobj_address

* Auto Commit for: fmgr_fwobj_address

* Auto Commit for: fmgr_fwobj_address

* Auto Commit for: fmgr_fwobj_address

* Commit contains updates to module, unit test, and/or fixture files: fmgr_fwobj_address
pull/53266/head
ftntcorecse 5 years ago committed by Nilashish Chakraborty
parent a65db027e8
commit c4d29868ca

@ -29,6 +29,8 @@ DOCUMENTATION = '''
---
module: fmgr_fwobj_address
version_added: "2.8"
notes:
- Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
author:
- Luke Weighall (@lweighall)
- Andrew Welsh (@Ghilli3)
@ -38,27 +40,17 @@ description:
- Allows for the management of IPv4, IPv6, and multicast address objects within FortiManager.
options:
host:
description:
- The FortiManager address.
required: true
username:
description:
- The username used to authenticate with the FortiManager.
required: true
password:
description:
- The password associated with the username account.
required: true
adom:
description:
- The ADOM the configuration should belong to.
required: false
default: root
allow_routing:
description:
- Enable/disable use of this address in the static route configuration.
choices: ['enable', 'disable']
default: 'disable'
associated_interface:
description:
@ -72,6 +64,7 @@ options:
description:
- Color of the object in FortiManager GUI.
- Takes integers 1-32
default: 22
comment:
description:
@ -152,6 +145,7 @@ options:
description:
- Enable/disable address visibility.
choices: ['enable', 'disable']
default: 'enable'
wildcard:
description:
@ -165,9 +159,6 @@ options:
EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "ipmask"
ipv4addr: "10.7.220.30/32"
name: "ansible_v4Obj"
@ -176,9 +167,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS OBJECT MORE OPTIONS
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "ipmask"
ipv4addr: "10.7.220.34/32"
name: "ansible_v4Obj_MORE"
@ -191,9 +179,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS SUBNET OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "ipmask"
ipv4addr: "10.7.220.0/255.255.255.128"
name: "ansible_subnet"
@ -202,9 +187,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS RANGE OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "iprange"
start_ip: "10.7.220.1"
end_ip: "10.7.220.125"
@ -213,9 +195,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS WILDCARD OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "wildcard"
wildcard: "10.7.220.30/255.255.255.255"
name: "ansible_wildcard"
@ -223,9 +202,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS WILDCARD FQDN OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "wildcard-fqdn"
wildcard_fqdn: "*.myds.com"
name: "Synology myds DDNS service"
@ -233,9 +209,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS FQDN OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "fqdn"
fqdn: "ansible.com"
name: "ansible_fqdn"
@ -243,9 +216,6 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS GEO OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "geography"
country: "usa"
name: "ansible_geo"
@ -253,9 +223,6 @@ EXAMPLES = '''
- name: ADD IPv6 ADDRESS
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv6: "ip"
ipv6addr: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
name: "ansible_v6Obj"
@ -263,9 +230,6 @@ EXAMPLES = '''
- name: ADD IPv6 ADDRESS RANGE
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv6: "iprange"
start_ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
end_ip: "2001:0db8:85a3:0000:0000:8a2e:0370:7446"
@ -274,27 +238,18 @@ EXAMPLES = '''
- name: ADD IPv4 IP ADDRESS GROUP
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "group"
group_name: "ansibleIPv4Group"
group_members: "ansible_fqdn, ansible_wildcard, ansible_range"
- name: ADD IPv6 IP ADDRESS GROUP
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv6: "group"
group_name: "ansibleIPv6Group"
group_members: "ansible_v6Obj, ansible_v6range"
- name: ADD MULTICAST RANGE
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
multicast: "multicastrange"
start_ip: "224.0.0.251"
end_ip: "224.0.0.251"
@ -303,9 +258,6 @@ EXAMPLES = '''
- name: ADD BROADCAST SUBNET
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
multicast: "broadcastmask"
ipv4addr: "10.7.220.0/24"
name: "ansible_broadcastSubnet"
@ -322,37 +274,22 @@ api_result:
import re
from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.network.fortimanager.fortimanager import AnsibleFortiManager
# check for pyFMG lib
try:
from pyFMG.fortimgr import FortiManager
HAS_PYFMGR = True
except ImportError:
HAS_PYFMGR = False
from ansible.module_utils.connection import Connection
from ansible.module_utils.network.fortimanager.fortimanager import FortiManagerHandler
from ansible.module_utils.network.fortimanager.common import FMGBaseException
from ansible.module_utils.network.fortimanager.common import FMGRCommon
from ansible.module_utils.network.fortimanager.common import DEFAULT_RESULT_OBJ
from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def fmgr_fwobj_tags(fmg, adom, tag):
def fmgr_fwobj_ipv4(fmgr, paramgram):
"""
This method sets tag objects so they can be used below
"""
# GET RID OF ANY WHITESPACE
tag = tag.strip()
datagram = {
"name": tag
}
url = '/pm/config/adom/{adom}/obj/system/object-tag'.format(adom=adom)
response = fmg.set(url, datagram)
return response
def fmgr_fwobj_ipv4(fmg, paramgram):
"""
This method sets a ipv4 address object
:param fmgr: The fmgr object instance from fortimanager.py
:type fmgr: class object
:param paramgram: The formatted dictionary of options to process
:type paramgram: dict
:return: The response from the FortiManager
:rtype: dict
"""
# EVAL THE MODE PARAMETER FOR SET OR ADD
if paramgram["mode"] in ['set', 'add']:
@ -372,14 +309,6 @@ def fmgr_fwobj_ipv4(fmg, paramgram):
"type": paramgram["ipv4"],
}
# # PROCESS TAGS
# if paramgram["tags"] is not None:
# tag_list = []
# for tag in paramgram["tags"].split(","):
# tag = tag.strip()
# tag_list.append(tag)
# datagram["tags"] = tag_list
# SET THE CORRECT URL BASED ON THE TYPE (WE'RE DOING GROUPS IN THIS METHOD, TOO)
if datagram["type"] == "group":
url = '/pm/config/adom/{adom}/obj/firewall/addrgrp'.format(adom=paramgram["adom"])
@ -402,7 +331,7 @@ def fmgr_fwobj_ipv4(fmg, paramgram):
if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]):
# IF THE SUBNET PARAMETER INPUT DIDN'T LOOK LIKE xxx.xxx.xxx.xxx TO REGEX...
# ... RUN IT THROUGH THE CIDR_TO_NETMASK() FUNCTION
mask = fmgr_cidr_to_netmask(subnet[1])
mask = fmgr._tools.cidr_to_netmask(subnet[1])
# AND THEN UPDATE THE SUBNET LIST OBJECT
subnet[1] = mask
@ -433,7 +362,7 @@ def fmgr_fwobj_ipv4(fmg, paramgram):
subnet.append(subnets)
if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]):
mask = fmgr_cidr_to_netmask(subnet[1])
mask = fmgr._tools.cidr_to_netmask(subnet[1])
subnet[1] = mask
datagram["wildcard"] = subnet
@ -463,14 +392,6 @@ def fmgr_fwobj_ipv4(fmg, paramgram):
"visibility": paramgram["visibility"]
}
# PROCESS TAGS
# if paramgram["tags"] is not None:
# tag_list = []
# for tag in paramgram["tags"].split(","):
# tag = tag.strip()
# tag_list.append(tag)
# datagram["tags"] = tag_list
members = []
group_members = paramgram["group_members"].replace(" ", "")
try:
@ -494,23 +415,18 @@ def fmgr_fwobj_ipv4(fmg, paramgram):
url = '/pm/config/adom/{adom}/obj/firewall/address/{name}'.format(adom=paramgram["adom"],
name=paramgram["name"])
# IF MODE = SET -- USE THE 'SET' API CALL MODE
if paramgram["mode"] == "set":
response = fmg.set(url, datagram)
return response
# IF MODE = ADD -- USE THE 'ADD' API CALL MODE
if paramgram["mode"] == "add":
response = fmg.add(url, datagram)
return response
# IF MODE = DELETE -- USE THE DELETE URL AND API CALL MODE
if paramgram["mode"] == "delete":
response = fmg.delete(url, datagram)
return response
response = fmgr.process_request(url, datagram, paramgram["mode"])
return response
def fmgr_fwobj_ipv6(fmg, paramgram):
def fmgr_fwobj_ipv6(fmgr, paramgram):
"""
This method sets a ipv6 address object
:param fmgr: The fmgr object instance from fortimanager.py
:type fmgr: class object
:param paramgram: The formatted dictionary of options to process
:type paramgram: dict
:return: The response from the FortiManager
:rtype: dict
"""
# EVAL THE MODE PARAMETER FOR SET OR ADD
if paramgram["mode"] in ['set', 'add']:
@ -526,14 +442,6 @@ def fmgr_fwobj_ipv6(fmg, paramgram):
"type": paramgram["ipv6"]
}
# PROCESS TAGS
# if paramgram["tags"] is not None:
# tag_list = []
# for tag in paramgram["tags"].split(","):
# tag = tag.strip()
# tag_list.append(tag)
# datagram["tags"] = tag_list
# SET THE CORRECT URL BASED ON THE TYPE (WE'RE DOING GROUPS IN THIS METHOD, TOO)
if datagram["type"] == "group":
url = '/pm/config/adom/{adom}/obj/firewall/addrgrp6'.format(adom=paramgram["adom"])
@ -566,14 +474,6 @@ def fmgr_fwobj_ipv6(fmg, paramgram):
"visibility": paramgram["visibility"]
}
# PROCESS TAGS
# if paramgram["tags"] is not None:
# tag_list = []
# for tag in paramgram["tags"].split(","):
# tag = tag.strip()
# tag_list.append(tag)
# datagram["tags"] = tag_list
members = []
group_members = paramgram["group_members"].replace(" ", "")
try:
@ -597,23 +497,18 @@ def fmgr_fwobj_ipv6(fmg, paramgram):
url = '/pm/config/adom/{adom}/obj/firewall/address6/{name}'.format(adom=paramgram["adom"],
name=paramgram["name"])
# IF MODE = SET -- USE THE 'SET' API CALL MODE
if paramgram["mode"] == "set":
response = fmg.set(url, datagram)
return response
# IF MODE = ADD -- USE THE 'ADD' API CALL MODE
if paramgram["mode"] == "add":
response = fmg.add(url, datagram)
return response
# IF MODE = DELETE -- USE THE DELETE URL AND API CALL MODE
if paramgram["mode"] == "delete":
response = fmg.delete(url, datagram)
return response
response = fmgr.process_request(url, datagram, paramgram["mode"])
return response
def fmgr_fwobj_multicast(fmg, paramgram):
def fmgr_fwobj_multicast(fmgr, paramgram):
"""
This method sets a multicast address object (ipv4 only as of this version).
:param fmgr: The fmgr object instance from fortimanager.py
:type fmgr: class object
:param paramgram: The formatted dictionary of options to process
:type paramgram: dict
:return: The response from the FortiManager
:rtype: dict
"""
# EVAL THE MODE PARAMETER FOR SET OR ADD
if paramgram["mode"] in ['set', 'add']:
@ -629,14 +524,6 @@ def fmgr_fwobj_multicast(fmg, paramgram):
"visibility": paramgram["visibility"],
}
# # PROCESS TAGS
# if paramgram["tags"] is not None:
# tag_list = []
# for tag in paramgram["tags"].split(","):
# tag = tag.strip()
# tag_list.append(tag)
# datagram["tags"] = tag_list
# SET THE CORRECT URL
url = '/pm/config/adom/{adom}/obj/firewall/multicast-address'.format(adom=paramgram["adom"])
@ -662,7 +549,7 @@ def fmgr_fwobj_multicast(fmg, paramgram):
if not re.match(r'\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}', subnet[1]):
# IF THE SUBNET PARAMETER INPUT DIDN'T LOOK LIKE 255.255.255.255 TO REGEX...
# ... RUN IT THROUGH THE fmgr_cidr_to_netmask() FUNCTION
mask = fmgr_cidr_to_netmask(subnet[1])
mask = fmgr._tools.cidr_to_netmask(subnet[1])
# AND THEN UPDATE THE SUBNET LIST OBJECT
subnet[1] = mask
@ -678,82 +565,19 @@ def fmgr_fwobj_multicast(fmg, paramgram):
url = '/pm/config/adom/{adom}/obj/firewall/multicast-address/{name}'.format(adom=paramgram["adom"],
name=paramgram["name"])
# IF MODE = SET -- USE THE 'SET' API CALL MODE
if paramgram["mode"] == "set":
response = fmg.set(url, datagram)
return response
# IF MODE = ADD -- USE THE 'ADD' API CALL MODE
if paramgram["mode"] == "add":
response = fmg.add(url, datagram)
return response
# IF MODE = DELETE -- USE THE DELETE URL AND API CALL MODE
if paramgram["mode"] == "delete":
response = fmg.delete(url, datagram)
return response
# ADDITIONAL COMMON FUNCTIONS
# FUNCTION/METHOD FOR LOGGING OUT AND ANALYZING ERROR CODES
def fmgr_logout(fmg, module, msg="NULL", results=(), good_codes=(0,), logout_on_fail=True, logout_on_success=False):
"""
THIS METHOD CONTROLS THE LOGOUT AND ERROR REPORTING AFTER AN METHOD OR FUNCTION RUNS
"""
# VALIDATION ERROR (NO RESULTS, JUST AN EXIT)
if msg != "NULL" and len(results) == 0:
try:
fmg.logout()
except Exception:
pass
module.fail_json(msg=msg)
# SUBMISSION ERROR
if len(results) > 0:
if msg == "NULL":
try:
msg = results[1]['status']['message']
except Exception:
msg = "No status message returned from pyFMG. Possible that this was a GET with a tuple result."
if results[0] not in good_codes:
if logout_on_fail:
fmg.logout()
module.fail_json(msg=msg, **results[1])
else:
return_msg = msg + " -- LOGOUT ON FAIL IS OFF, MOVING ON"
return return_msg
else:
if logout_on_success:
fmg.logout()
module.exit_json(msg=msg, **results[1])
else:
return_msg = msg + " -- LOGOUT ON SUCCESS IS OFF, MOVING ON TO REST OF CODE"
return return_msg
# FUNCTION/METHOD FOR CONVERTING CIDR TO A NETMASK
# DID NOT USE IP ADDRESS MODULE TO KEEP INCLUDES TO A MINIMUM
def fmgr_cidr_to_netmask(cidr):
cidr = int(cidr)
mask = (0xffffffff >> (32 - cidr)) << (32 - cidr)
return(str((0xff000000 & mask) >> 24) + '.' +
str((0x00ff0000 & mask) >> 16) + '.' +
str((0x0000ff00 & mask) >> 8) + '.' +
str((0x000000ff & mask)))
response = fmgr.process_request(url, datagram, paramgram["mode"])
return response
def main():
argument_spec = dict(
adom=dict(required=False, type="str"),
host=dict(required=True, type="str"),
password=dict(fallback=(env_fallback, ["ANSIBLE_NET_PASSWORD"]), no_log=True),
username=dict(fallback=(env_fallback, ["ANSIBLE_NET_USERNAME"]), no_log=True),
adom=dict(required=False, type="str", default="root"),
mode=dict(choices=["add", "set", "delete"], type="str", default="add"),
allow_routing=dict(required=False, type="str", choices=['enable', 'disable']),
allow_routing=dict(required=False, type="str", choices=['enable', 'disable'], default="disable"),
associated_interface=dict(required=False, type="str"),
cache_ttl=dict(required=False, type="str"),
color=dict(required=False, type="str"),
color=dict(required=False, type="str", default=22),
comment=dict(required=False, type="str"),
country=dict(required=False, type="str"),
fqdn=dict(required=False, type="str"),
@ -762,7 +586,7 @@ def main():
end_ip=dict(required=False, type="str"),
ipv4=dict(required=False, type="str", choices=['ipmask', 'iprange', 'fqdn', 'wildcard',
'geography', 'wildcard-fqdn', 'group']),
visibility=dict(required=False, type="str", choices=['enable', 'disable']),
visibility=dict(required=False, type="str", choices=['enable', 'disable'], default="enable"),
wildcard=dict(required=False, type="str"),
wildcard_fqdn=dict(required=False, type="str"),
ipv6=dict(required=False, type="str", choices=['ip', 'iprange', 'group']),
@ -775,84 +599,63 @@ def main():
)
module = AnsibleModule(argument_spec, supports_check_mode=False, )
# CHECK IF THE HOST/USERNAME/PW EXISTS, AND IF IT DOES, LOGIN.
host = module.params["host"]
password = module.params["password"]
username = module.params["username"]
if host is None or username is None:
module.fail_json(msg="Host and username are required")
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False,
mutually_exclusive=[
['ipv4', 'ipv6'],
['ipv4', 'multicast'],
['ipv6', 'multicast']
])
paramgram = {
"adom": module.params["adom"],
"allow-routing": module.params["allow_routing"],
"associated-interface": module.params["associated_interface"],
"cache-ttl": module.params["cache_ttl"],
"color": module.params["color"],
"comment": module.params["comment"],
"country": module.params["country"],
"end-ip": module.params["end_ip"],
"fqdn": module.params["fqdn"],
"name": module.params["name"],
"start-ip": module.params["start_ip"],
"visibility": module.params["visibility"],
"wildcard": module.params["wildcard"],
"wildcard-fqdn": module.params["wildcard_fqdn"],
"ipv6": module.params["ipv6"],
"ipv4": module.params["ipv4"],
"group_members": module.params["group_members"],
"group_name": module.params["group_name"],
"ipv4addr": module.params["ipv4addr"],
"ipv6addr": module.params["ipv6addr"],
"multicast": module.params["multicast"],
"mode": module.params["mode"],
"obj-id": module.params["obj_id"],
}
# CHECK IF LOGIN FAILED
fmg = AnsibleFortiManager(module, module.params["host"], module.params["username"], module.params["password"])
module.paramgram = paramgram
fmgr = None
if module._socket_path:
connection = Connection(module._socket_path)
fmgr = FortiManagerHandler(connection, module)
fmgr._tools = FMGRCommon()
else:
module.fail_json(**FAIL_SOCKET_MSG)
results = DEFAULT_RESULT_OBJ
try:
response = fmg.login()
if response[1]['status']['code'] != 0:
module.fail_json(msg="Connection to FortiManager Failed")
except Exception:
module.fail_json(msg="Connection to FortiManager Failed")
else:
# START SESSION LOGIC
# MODULE PARAMGRAM
paramgram = {
"adom": module.params["adom"],
"allow-routing": module.params["allow_routing"],
"associated-interface": module.params["associated_interface"],
"cache-ttl": module.params["cache_ttl"],
"color": module.params["color"],
"comment": module.params["comment"],
"country": module.params["country"],
"end-ip": module.params["end_ip"],
"fqdn": module.params["fqdn"],
"name": module.params["name"],
"start-ip": module.params["start_ip"],
"visibility": module.params["visibility"],
"wildcard": module.params["wildcard"],
"wildcard-fqdn": module.params["wildcard_fqdn"],
"ipv6": module.params["ipv6"],
"ipv4": module.params["ipv4"],
"group_members": module.params["group_members"],
"group_name": module.params["group_name"],
"ipv4addr": module.params["ipv4addr"],
"ipv6addr": module.params["ipv6addr"],
"multicast": module.params["multicast"],
"mode": module.params["mode"],
"obj-id": module.params["obj_id"],
}
if paramgram["ipv4"]:
results = fmgr_fwobj_ipv4(fmgr, paramgram)
elif paramgram["ipv6"]:
results = fmgr_fwobj_ipv6(fmgr, paramgram)
elif paramgram["multicast"]:
results = fmgr_fwobj_multicast(fmgr, paramgram)
fmgr.govern_response(module=module, results=results,
ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
if paramgram["adom"] is None:
paramgram["adom"] = "root"
if paramgram["mode"] is None:
paramgram["mode"] = "add"
if paramgram["color"] is None:
paramgram["color"] = 22
if paramgram["comment"] is None:
paramgram["comment"] = "Created by Ansible"
if paramgram["allow-routing"] is None:
paramgram["allow-routing"] = "disable"
if paramgram["visibility"] is None:
paramgram["visibility"] = "enable"
if paramgram["ipv4"] is not None and paramgram["ipv6"] is None and paramgram["multicast"] is None:
# PROCESS IPv4
results = fmgr_fwobj_ipv4(fmg, paramgram)
fmgr_logout(fmg, module, results=results, good_codes=[0, -2, -3])
if paramgram["ipv4"] is None and paramgram["ipv6"] is not None and paramgram["multicast"] is None:
# PROCESS IPv6
results = fmgr_fwobj_ipv6(fmg, paramgram)
if results[0] not in [0, -2, -3]:
module.fail_json(msg="Failed to process IPv6 Object", **results[1])
if paramgram["ipv4"] is None and paramgram["ipv6"] is None and paramgram["multicast"] is not None:
# PROCESS MULTICAST
results = fmgr_fwobj_multicast(fmg, paramgram)
if results[0] not in [0, -2, -3]:
module.fail_json(msg="Failed to process Multicast Object", **results[1])
fmg.logout()
except Exception as err:
raise FMGBaseException(err)
if results is not None:
return module.exit_json(**results[1])

Loading…
Cancel
Save