Fortinet FortiManager Firewall Objects - Addresses (#46084)

* fmgr_fwobj_address PR candidate

* fmgr_fwobj_address PR candidate

* PR candidate

* PR candidate

* Adding requested changes by @samccann

* minor issue...

* minor pylint issue

* More changes from @samccann

* more grammar

* Author Mention Change

* Fixing Authors
This commit is contained in:
ftntcorecse 2018-11-20 23:30:39 -07:00 committed by Nilashish Chakraborty
parent 86222fd4c4
commit 1da3c5c302
3 changed files with 3249 additions and 0 deletions

View file

@ -0,0 +1,865 @@
#!/usr/bin/python
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.1",
"status": ["preview"],
"supported_by": "community"
}
DOCUMENTATION = '''
---
module: fmgr_fwobj_address
version_added: "2.8"
author:
- Luke Weighall (@lweighall)
- Andrew Welsh (@Ghilli3)
- Jim Huber (@p4r4n0y1ng)
short_description: Allows the management of firewall objects in FortiManager
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.
allow_routing:
description:
- Enable/disable use of this address in the static route configuration.
choices: ['enable', 'disable']
associated_interface:
description:
- Associated interface name.
cache_ttl:
description:
- Minimal TTL of individual IP addresses in FQDN cache. Only applies when type = wildcard-fqdn.
color:
description:
- Color of the object in FortiManager GUI.
- Takes integers 1-32
comment:
description:
- Comment for the object in FortiManager.
country:
description:
- Country name. Required if type = geographic.
end_ip:
description:
- End IP. Only used when ipv4 = iprange.
group_members:
description:
- Address group member. If this is defined w/out group_name, the operation will fail.
group_name:
description:
- Address group name. If this is defined in playbook task, all other options are ignored.
ipv4:
description:
- Type of IPv4 Object.
- Must not be specified with either multicast or IPv6 parameters.
choices: ['ipmask', 'iprange', 'fqdn', 'wildcard', 'geography', 'wildcard-fqdn', 'group']
ipv4addr:
description:
- IP and network mask. If only defining one IP use this parameter. (i.e. 10.7.220.30/255.255.255.255)
- Can also define subnets (i.e. 10.7.220.0/255.255.255.0)
- Also accepts CIDR (i.e. 10.7.220.0/24)
- If Netmask is omitted after IP address, /32 is assumed.
- When multicast is set to Broadcast Subnet the ipv4addr parameter is used to specify the subnet.
ipv6:
description:
- Puts module into IPv6 mode.
- Must not be specified with either ipv4 or multicast parameters.
choices: ['ip', 'iprange', 'group']
ipv6addr:
description:
- IPv6 address in full. (i.e. 2001:0db8:85a3:0000:0000:8a2e:0370:7334)
fqdn:
description:
- Fully qualified domain name.
mode:
description:
- Sets one of three modes for managing the object.
choices: ['add', 'set', 'delete']
default: add
multicast:
description:
- Manages Multicast Address Objects.
- Sets either a Multicast IP Range or a Broadcast Subnet.
- Must not be specified with either ipv4 or ipv6 parameters.
- When set to Broadcast Subnet the ipv4addr parameter is used to specify the subnet.
- Can create IPv4 Multicast Objects (multicastrange and broadcastmask options -- uses start/end-ip and ipv4addr).
choices: ['multicastrange', 'broadcastmask', 'ip6']
name:
description:
- Friendly Name Address object name in FortiManager.
obj_id:
description:
- Object ID for NSX.
start_ip:
description:
- Start IP. Only used when ipv4 = iprange.
visibility:
description:
- Enable/disable address visibility.
choices: ['enable', 'disable']
wildcard:
description:
- IP address and wildcard netmask. Required if ipv4 = wildcard.
wildcard_fqdn:
description:
- Wildcard FQDN. Required if ipv4 = wildcard-fqdn.
'''
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"
comment: "Created by Ansible"
color: "6"
- 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"
comment: "Created by Ansible"
color: "6"
allow_routing: "enable"
cache_ttl: "180"
associated_interface: "port1"
obj_id: "123"
- 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"
comment: "Created by Ansible"
mode: "set"
- 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"
name: "ansible_range"
comment: "Created by Ansible"
- 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"
comment: "Created by Ansible"
- 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"
comment: "Created by Ansible"
- 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"
comment: "Created by Ansible"
- name: ADD IPv4 IP ADDRESS GEO OBJECT
fmgr_fwobj_address:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
ipv4: "geography"
country: "usa"
name: "ansible_geo"
comment: "Created by Ansible"
- 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"
comment: "Created by Ansible"
- 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"
name: "ansible_v6range"
comment: "Created by Ansible"
- 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"
name: "ansible_multicastrange"
comment: "Created by Ansible"
- 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"
comment: "Created by Ansible"
'''
RETURN = """
api_result:
description: full API response, includes status code and message
returned: always
type: string
"""
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
def fmgr_fwobj_tags(fmg, adom, tag):
"""
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
"""
# EVAL THE MODE PARAMETER FOR SET OR ADD
if paramgram["mode"] in ['set', 'add']:
# CREATE THE DATAGRAM DICTIONARY
# ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE
# SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED
datagram = {
"comment": paramgram["comment"],
"associated-interface": paramgram["associated-interface"],
"cache-ttl": paramgram["cache-ttl"],
"name": paramgram["name"],
"allow-routing": paramgram["allow-routing"],
"color": paramgram["color"],
"meta fields": {},
"dynamic_mapping": [],
"visibility": paramgram["allow-routing"],
"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"])
else:
url = '/pm/config/adom/{adom}/obj/firewall/address'.format(adom=paramgram["adom"])
#########################
# IF type = 'ipmask'
#########################
if datagram["type"] == "ipmask":
# CREATE THE SUBNET LIST OBJECT
subnet = []
# EVAL THE IPV4ADDR INPUT AND SPLIT THE IP ADDRESS FROM THE MASK AND APPEND THEM TO THE SUBNET LIST
for subnets in paramgram["ipv4addr"].split("/"):
subnet.append(subnets)
# CHECK THAT THE SECOND ENTRY IN THE SUBNET LIST (WHAT WAS TO THE RIGHT OF THE / CHARACTER)
# IS IN SUBNET MASK FORMAT AND NOT CIDR FORMAT.
# IF IT IS IN CIDR FORMAT, WE NEED TO CONVERT IT TO SUBNET BIT MASK FORMAT FOR THE JSON API
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])
# AND THEN UPDATE THE SUBNET LIST OBJECT
subnet[1] = mask
# INCLUDE THE SUBNET LIST OBJECT IN THE DATAGRAM DICTIONARY TO BE SUBMITTED
datagram["subnet"] = subnet
#########################
# IF type = 'iprange'
#########################
if datagram["type"] == "iprange":
datagram["start-ip"] = paramgram["start-ip"]
datagram["end-ip"] = paramgram["end-ip"]
datagram["subnet"] = ["0.0.0.0", "0.0.0.0"]
#########################
# IF type = 'geography'
#########################
if datagram["type"] == "geography":
datagram["country"] = paramgram["country"]
#########################
# IF type = 'wildcard'
#########################
if datagram["type"] == "wildcard":
subnet = []
for subnets in paramgram["wildcard"].split("/"):
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])
subnet[1] = mask
datagram["wildcard"] = subnet
#########################
# IF type = 'wildcard-fqdn'
#########################
if datagram["type"] == "wildcard-fqdn":
datagram["wildcard-fqdn"] = paramgram["wildcard-fqdn"]
#########################
# IF type = 'fqdn'
#########################
if datagram["type"] == "fqdn":
datagram["fqdn"] = paramgram["fqdn"]
#########################
# IF type = 'group'
#########################
if datagram["type"] == "group":
datagram = {
"comment": paramgram["comment"],
"name": paramgram["group_name"],
"color": paramgram["color"],
"meta fields": {},
"dynamic_mapping": [],
"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:
for member in group_members.split(","):
members.append(member)
except:
pass
datagram["member"] = members
# EVAL THE MODE PARAMETER FOR DELETE
if paramgram["mode"] == "delete":
# IF A GROUP, SET THE CORRECT NAME AND URL FOR THE GROUP ENDPOINT
if paramgram["ipv4"] == "group":
datagram = {}
url = '/pm/config/adom/{adom}/obj/firewall/addrgrp/{name}'.format(adom=paramgram["adom"],
name=paramgram["group_name"])
# OTHERWISE WE'RE JUST GOING TO USE THE ADDRESS ENDPOINT
else:
datagram = {}
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
def fmgr_fwobj_ipv6(fmg, paramgram):
"""
This method sets a ipv6 address object
"""
# EVAL THE MODE PARAMETER FOR SET OR ADD
if paramgram["mode"] in ['set', 'add']:
# CREATE THE DATAGRAM DICTIONARY
# ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE
# SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED
datagram = {
"comment": paramgram["comment"],
"name": paramgram["name"],
"color": paramgram["color"],
"dynamic_mapping": [],
"visibility": paramgram["visibility"],
"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"])
else:
url = '/pm/config/adom/{adom}/obj/firewall/address6'.format(adom=paramgram["adom"])
#########################
# IF type = 'ip'
#########################
if datagram["type"] == "ip":
datagram["type"] = "ipprefix"
datagram["ip6"] = paramgram["ipv6addr"]
#########################
# IF type = 'iprange'
#########################
if datagram["type"] == "iprange":
datagram["start-ip"] = paramgram["start-ip"]
datagram["end-ip"] = paramgram["end-ip"]
#########################
# IF type = 'group'
#########################
if datagram["type"] == "group":
datagram = None
datagram = {
"comment": paramgram["comment"],
"name": paramgram["group_name"],
"color": paramgram["color"],
"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:
for member in group_members.split(","):
members.append(member)
except:
pass
datagram["member"] = members
# EVAL THE MODE PARAMETER FOR DELETE
if paramgram["mode"] == "delete":
# IF A GROUP, SET THE CORRECT NAME AND URL FOR THE GROUP ENDPOINT
if paramgram["ipv6"] == "group":
datagram = {}
url = '/pm/config/adom/{adom}/obj/firewall/addrgrp6/{name}'.format(adom=paramgram["adom"],
name=paramgram["group_name"])
# OTHERWISE WE'RE JUST GOING TO USE THE ADDRESS ENDPOINT
else:
datagram = {}
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
def fmgr_fwobj_multicast(fmg, paramgram):
"""
This method sets a multicast address object (ipv4 only as of this version).
"""
# EVAL THE MODE PARAMETER FOR SET OR ADD
if paramgram["mode"] in ['set', 'add']:
# CREATE THE DATAGRAM DICTIONARY
# ENSURE THE DATAGRAM KEYS MATCH THE JSON API GUIDE ATTRIBUTES, NOT WHAT IS IN ANSIBLE
# SOME PARAMETERS SHOWN IN THIS DICTIONARY WE DON'T EVEN ASK THE USER FOR IN PLAYBOOKS BUT ARE REQUIRED
datagram = {
"associated-interface": paramgram["associated-interface"],
"comment": paramgram["comment"],
"name": paramgram["name"],
"color": paramgram["color"],
"type": paramgram["multicast"],
"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"])
#########################
# IF type = 'multicastrange'
#########################
if paramgram["multicast"] == "multicastrange":
datagram["start-ip"] = paramgram["start-ip"]
datagram["end-ip"] = paramgram["end-ip"]
datagram["subnet"] = ["0.0.0.0", "0.0.0.0"]
#########################
# IF type = 'broadcastmask'
#########################
if paramgram["multicast"] == "broadcastmask":
# EVAL THE IPV4ADDR INPUT AND SPLIT THE IP ADDRESS FROM THE MASK AND APPEND THEM TO THE SUBNET LIST
subnet = []
for subnets in paramgram["ipv4addr"].split("/"):
subnet.append(subnets)
# CHECK THAT THE SECOND ENTRY IN THE SUBNET LIST (WHAT WAS TO THE RIGHT OF THE / CHARACTER)
# IS IN SUBNET MASK FORMAT AND NOT CIDR FORMAT.
# IF IT IS IN CIDR FORMAT, WE NEED TO CONVERT IT TO SUBNET BIT MASK FORMAT FOR THE JSON API
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])
# AND THEN UPDATE THE SUBNET LIST OBJECT
subnet[1] = mask
# INCLUDE THE SUBNET LIST OBJECT IN THE DATAGRAM DICTIONARY TO BE SUBMITTED
datagram["subnet"] = subnet
# EVAL THE MODE PARAMETER FOR DELETE
if paramgram["mode"] == "delete":
datagram = {
"name": paramgram["name"]
}
# SET THE CORRECT URL FOR DELETE
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:
pass
module.fail_json(msg=msg)
# SUBMISSION ERROR
if len(results) > 0:
if msg == "NULL":
try:
msg = results[1]['status']['message']
except:
msg = "No status message returned from pyFMG. Possible that this was a GET with a tuple result."
if results[0] not in good_codes:
if logout_on_fail:
fmg.logout()
module.fail_json(msg=msg, **results[1])
else:
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)))
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),
mode=dict(choices=["add", "set", "delete"], type="str", default="add"),
allow_routing=dict(required=False, type="str", choices=['enable', 'disable']),
associated_interface=dict(required=False, type="str"),
cache_ttl=dict(required=False, type="str"),
color=dict(required=False, type="str"),
comment=dict(required=False, type="str"),
country=dict(required=False, type="str"),
fqdn=dict(required=False, type="str"),
name=dict(required=False, type="str"),
start_ip=dict(required=False, type="str"),
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']),
wildcard=dict(required=False, type="str"),
wildcard_fqdn=dict(required=False, type="str"),
ipv6=dict(required=False, type="str", choices=['ip', 'iprange', 'group']),
group_members=dict(required=False, type="str"),
group_name=dict(required=False, type="str"),
ipv4addr=dict(required=False, type="str"),
ipv6addr=dict(required=False, type="str"),
multicast=dict(required=False, type="str", choices=['multicastrange', 'broadcastmask', 'ip6']),
obj_id=dict(required=False, type="str"),
)
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")
# CHECK IF LOGIN FAILED
fmg = AnsibleFortiManager(module, module.params["host"], module.params["username"], module.params["password"])
try:
response = fmg.login()
if response[1]['status']['code'] != 0:
module.fail_json(msg="Connection to FortiManager Failed")
except:
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["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()
if results is not None:
return module.exit_json(**results[1])
else:
return module.exit_json(msg="Couldn't find a proper ipv4 or ipv6 or multicast parameter "
"to run in the logic tree. Exiting...")
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff