From fb545b72c3e363b3006c3da88d91ed3354711b7f Mon Sep 17 00:00:00 2001 From: Ivan Bojer Date: Sat, 3 Feb 2018 03:34:04 -0800 Subject: [PATCH] new module that allows for adding DynamicAddressGroup tags to the firewall (#35201) * new module that allows for adding dag tags --- CHANGELOG.md | 1 + .../modules/network/panos/panos_dag_tags.py | 246 ++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 lib/ansible/modules/network/panos/panos_dag_tags.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 9521f675ba2..cbf6bbb4ec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -328,6 +328,7 @@ See [Porting Guide](http://docs.ansible.com/ansible/devel/porting_guides.html) f * onyx_vlan - panos * panos_query_rules + * panos_dag_tags - radware * vdirect_commit * vdirect_runnable diff --git a/lib/ansible/modules/network/panos/panos_dag_tags.py b/lib/ansible/modules/network/panos/panos_dag_tags.py new file mode 100644 index 00000000000..f506ad09350 --- /dev/null +++ b/lib/ansible/modules/network/panos/panos_dag_tags.py @@ -0,0 +1,246 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Ansible module to manage PaloAltoNetworks Firewall +# (c) 2016, techbizdev +# +# 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 . +# limitations under the License. + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = ''' +--- +module: panos_dag_tags +short_description: Create tags for DAG's on PAN-OS devices. +description: + - Create the ip address to tag associations. Tags will in turn be used to create DAG's +author: "Vinay Venkataraghavan (@vinayvenkat)" +version_added: "2.5" +requirements: + - pan-python can be obtained from PyPi U(https://pypi.python.org/pypi/pan-python) + - pandevice can be obtained from PyPi U(https://pypi.python.org/pypi/pandevice) +notes: + - Checkmode is not supported. + - Panorama is not supported. +options: + ip_address: + description: + - IP address (or hostname) of PAN-OS device + required: true + password: + description: + - password for authentication + required: true + api_key: + description: + - API key that can be used instead of I(username)/I(password) credentials. + username: + description: + - username for authentication + default: "admin" + description: + description: + - The purpose / objective of the static Address Group + commit: + description: + - commit if changed + default: true + devicegroup: + description: > + - Device groups are used for the Panorama interaction with Firewall(s). The group must exists on Panorama. + If device group is not define we assume that we are contacting Firewall. + operation: + description: + - The action to be taken. Supported values are I(add)/I(update)/I(find)/I(delete). + tag_names: + description: + - The list of the tags that will be added or removed from the IP address. + ip_to_register: + description: + - IP that will be registered with the given tag names. +''' + +EXAMPLES = ''' +- name: Create the tags to map IP addresses + panos_dag_tags: + ip_address: "{{ ip_address }}" + password: "{{ password }}" + ip_to_register: "{{ ip_to_register }}" + tag_names: "{{ tag_names }}" + description: "Tags to allow certain IP's to access various SaaS Applications" + operation: 'add' + tags: "adddagip" + +- name: List the IP address to tag mapping + panos_dag_tags: + ip_address: "{{ ip_address }}" + password: "{{ password }}" + tag_names: "{{ tag_names }}" + description: "List the IP address to tag mapping" + operation: 'list' + tags: "listdagip" + +- name: Unregister an IP address from a tag mapping + panos_dag_tags: + ip_address: "{{ ip_address }}" + password: "{{ password }}" + ip_to_register: "{{ ip_to_register }}" + tag_names: "{{ tag_names }}" + description: "Unregister IP address from tag mappings" + operation: 'delete' + tags: "deletedagip" +''' + +RETURN = ''' +# Default return values +''' + +from ansible.module_utils.basic import AnsibleModule, get_exception + +try: + from pandevice import base + from pandevice import firewall + from pandevice import panorama + from pandevice import objects + + from pan.xapi import PanXapiError + + HAS_LIB = True +except ImportError: + HAS_LIB = False + + +def get_devicegroup(device, devicegroup): + dg_list = device.refresh_devices() + for group in dg_list: + if isinstance(group, panorama.DeviceGroup): + if group.name == devicegroup: + return group + return False + + +def register_ip_to_tag_map(device, ip_addresses, tag): + exc = None + try: + device.userid.register(ip_addresses, tag) + except PanXapiError: + exc = get_exception() + + if exc: + return False, exc + + return True, exc + + +def get_all_address_group_mapping(device): + exc = None + ret = None + try: + ret = device.userid.get_registered_ip() + except PanXapiError: + exc = get_exception() + + if exc: + return False, exc + + return ret, exc + + +def delete_address_from_mapping(device, ip_address, tags): + exc = None + try: + ret = device.userid.unregister(ip_address, tags) + except PanXapiError: + exc = get_exception() + + if exc: + return False, exc + + return True, exc + + +def main(): + argument_spec = dict( + ip_address=dict(required=True), + password=dict(required=True, no_log=True), + username=dict(default='admin'), + api_key=dict(no_log=True), + devicegroup=dict(default=None), + description=dict(default=None), + ip_to_register=dict(type='str', required=False), + tag_names=dict(type='list', required=True), + commit=dict(type='bool', default=True), + operation=dict(type='str', required=True) + ) + + module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) + if not HAS_LIB: + module.fail_json(msg='pan-python is required for this module') + + ip_address = module.params["ip_address"] + password = module.params["password"] + username = module.params['username'] + api_key = module.params['api_key'] + commit = module.params['commit'] + devicegroup = module.params['devicegroup'] + operation = module.params['operation'] + + # Create the device with the appropriate pandevice type + device = base.PanDevice.create_from_device(ip_address, username, password, api_key=api_key) + + # If Panorama, validate the devicegroup + dev_group = None + if devicegroup and isinstance(device, panorama.Panorama): + dev_group = get_devicegroup(device, devicegroup) + if dev_group: + device.add(dev_group) + else: + module.fail_json(msg='\'%s\' device group not found in Panorama. Is the name correct?' % devicegroup) + + result = None + if operation == 'add': + result, exc = register_ip_to_tag_map(device, + ip_addresses=module.params.get('ip_to_register', None), + tag=module.params.get('tag_names', None) + ) + elif operation == 'list': + result, exc = get_all_address_group_mapping(device) + elif operation == 'delete': + result, exc = delete_address_from_mapping(device, + ip_address=module.params.get('ip_to_register', None), + tags=module.params.get('tag_names', []) + ) + else: + module.fail_json(msg="Unsupported option") + + if not result: + module.fail_json(msg=exc.message) + + if commit: + try: + device.commit(sync=True) + except PanXapiError: + exc = get_exception() + module.fail_json(msg=exc) + + module.exit_json(changed=True, msg=result) + + +if __name__ == "__main__": + main()