mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 00:55:19 +00:00
commit
9927fd315a
38
salt/grains/panos.py
Normal file
38
salt/grains/panos.py
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Generate baseline proxy minion grains for panos hosts.
|
||||
|
||||
'''
|
||||
|
||||
# Import Python Libs
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
|
||||
# Import Salt Libs
|
||||
import salt.utils.platform
|
||||
import salt.proxy.panos
|
||||
|
||||
__proxyenabled__ = ['panos']
|
||||
__virtualname__ = 'panos'
|
||||
|
||||
log = logging.getLogger(__file__)
|
||||
|
||||
GRAINS_CACHE = {'os_family': 'panos'}
|
||||
|
||||
|
||||
def __virtual__():
|
||||
try:
|
||||
if salt.utils.platform.is_proxy() and __opts__['proxy']['proxytype'] == 'panos':
|
||||
return __virtualname__
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def panos(proxy=None):
|
||||
if not proxy:
|
||||
return {}
|
||||
if proxy['panos.initialized']() is False:
|
||||
return {}
|
||||
return {'panos': proxy['panos.grains']()}
|
1857
salt/modules/panos.py
Normal file
1857
salt/modules/panos.py
Normal file
File diff suppressed because it is too large
Load Diff
418
salt/proxy/panos.py
Normal file
418
salt/proxy/panos.py
Normal file
@ -0,0 +1,418 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
|
||||
Proxy Minion interface module for managing Palo Alto firewall devices.
|
||||
|
||||
:codeauthor: :email:`Spencer Ervin <spencer_ervin@hotmail.com>`
|
||||
:maturity: new
|
||||
:depends: none
|
||||
:platform: unix
|
||||
|
||||
This proxy minion enables Palo Alto firewalls (hereafter referred to
|
||||
as simply 'panos') to be treated individually like a Salt Minion.
|
||||
|
||||
The panos proxy leverages the XML API functionality on the Palo Alto
|
||||
firewall. The Salt proxy must have access to the Palo Alto firewall on
|
||||
HTTPS (tcp/443).
|
||||
|
||||
More in-depth conceptual reading on Proxy Minions can be found in the
|
||||
:ref:`Proxy Minion <proxy-minion>` section of Salt's
|
||||
documentation.
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
To use this integration proxy module, please configure the following:
|
||||
|
||||
Pillar
|
||||
------
|
||||
|
||||
Proxy minions get their configuration from Salt's Pillar. Every proxy must
|
||||
have a stanza in Pillar and a reference in the Pillar top-file that matches
|
||||
the ID. There are four connection options available for the panos proxy module.
|
||||
|
||||
- Direct Device (Password)
|
||||
- Direct Device (API Key)
|
||||
- Panorama Pass-Through (Password)
|
||||
- Panorama Pass-Through (API Key)
|
||||
|
||||
|
||||
Direct Device (Password)
|
||||
------------------------
|
||||
|
||||
The direct device configuration configures the proxy to connect directly to
|
||||
the device with username and password.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
proxy:
|
||||
proxytype: panos
|
||||
host: <ip or dns name of panos host>
|
||||
username: <panos username>
|
||||
password: <panos password>
|
||||
|
||||
proxytype
|
||||
^^^^^^^^^
|
||||
The ``proxytype`` key and value pair is critical, as it tells Salt which
|
||||
interface to load from the ``proxy`` directory in Salt's install hierarchy,
|
||||
or from ``/srv/salt/_proxy`` on the Salt Master (if you have created your
|
||||
own proxy module, for example). To use this panos Proxy Module, set this to
|
||||
``panos``.
|
||||
|
||||
host
|
||||
^^^^
|
||||
The location, or ip/dns, of the panos host. Required.
|
||||
|
||||
username
|
||||
^^^^^^^^
|
||||
The username used to login to the panos host. Required.
|
||||
|
||||
password
|
||||
^^^^^^^^
|
||||
The password used to login to the panos host. Required.
|
||||
|
||||
Direct Device (API Key)
|
||||
------------------------
|
||||
|
||||
Palo Alto devices allow for access to the XML API with a generated 'API key'_
|
||||
instead of username and password.
|
||||
|
||||
.. _API key: https://www.paloaltonetworks.com/documentation/71/pan-os/xml-api/get-started-with-the-pan-os-xml-api/get-your-api-key
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
proxy:
|
||||
proxytype: panos
|
||||
host: <ip or dns name of panos host>
|
||||
apikey: <panos generated api key>
|
||||
|
||||
proxytype
|
||||
^^^^^^^^^
|
||||
The ``proxytype`` key and value pair is critical, as it tells Salt which
|
||||
interface to load from the ``proxy`` directory in Salt's install hierarchy,
|
||||
or from ``/srv/salt/_proxy`` on the Salt Master (if you have created your
|
||||
own proxy module, for example). To use this panos Proxy Module, set this to
|
||||
``panos``.
|
||||
|
||||
host
|
||||
^^^^
|
||||
The location, or ip/dns, of the panos host. Required.
|
||||
|
||||
apikey
|
||||
^^^^^^^^
|
||||
The generated XML API key for the panos host. Required.
|
||||
|
||||
Panorama Pass-Through (Password)
|
||||
------------------------
|
||||
|
||||
The Panorama pass-through method sends all connections through the Panorama
|
||||
management system. It passes the connections to the appropriate device using
|
||||
the serial number of the Palo Alto firewall.
|
||||
|
||||
This option will reduce the number of connections that must be present for the
|
||||
proxy server. It will only require a connection to the Panorama server.
|
||||
|
||||
The username and password will be for authentication to the Panorama server,
|
||||
not the panos device.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
proxy:
|
||||
proxytype: panos
|
||||
serial: <serial number of panos host>
|
||||
host: <ip or dns name of the panorama server>
|
||||
username: <panorama server username>
|
||||
password: <panorama server password>
|
||||
|
||||
proxytype
|
||||
^^^^^^^^^
|
||||
The ``proxytype`` key and value pair is critical, as it tells Salt which
|
||||
interface to load from the ``proxy`` directory in Salt's install hierarchy,
|
||||
or from ``/srv/salt/_proxy`` on the Salt Master (if you have created your
|
||||
own proxy module, for example). To use this panos Proxy Module, set this to
|
||||
``panos``.
|
||||
|
||||
serial
|
||||
^^^^^^
|
||||
The serial number of the panos host. Required.
|
||||
|
||||
host
|
||||
^^^^
|
||||
The location, or ip/dns, of the Panorama server. Required.
|
||||
|
||||
username
|
||||
^^^^^^^^
|
||||
The username used to login to the Panorama server. Required.
|
||||
|
||||
password
|
||||
^^^^^^^^
|
||||
The password used to login to the Panorama server. Required.
|
||||
|
||||
Panorama Pass-Through (API Key)
|
||||
------------------------
|
||||
|
||||
The Panorama server can also utilize a generated 'API key'_ for authentication.
|
||||
|
||||
.. _API key: https://www.paloaltonetworks.com/documentation/71/pan-os/xml-api/get-started-with-the-pan-os-xml-api/get-your-api-key
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
proxy:
|
||||
proxytype: panos
|
||||
serial: <serial number of panos host>
|
||||
host: <ip or dns name of the panorama server>
|
||||
apikey: <panos generated api key>
|
||||
|
||||
proxytype
|
||||
^^^^^^^^^
|
||||
The ``proxytype`` key and value pair is critical, as it tells Salt which
|
||||
interface to load from the ``proxy`` directory in Salt's install hierarchy,
|
||||
or from ``/srv/salt/_proxy`` on the Salt Master (if you have created your
|
||||
own proxy module, for example). To use this panos Proxy Module, set this to
|
||||
``panos``.
|
||||
|
||||
serial
|
||||
^^^^^^
|
||||
The serial number of the panos host. Required.
|
||||
|
||||
host
|
||||
^^^^
|
||||
The location, or ip/dns, of the Panorama server. Required.
|
||||
|
||||
apikey
|
||||
^^^^^^^^
|
||||
The generated XML API key for the Panorama server. Required.
|
||||
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Python Libs
|
||||
import logging
|
||||
|
||||
# Import Salt Libs
|
||||
import salt.exceptions
|
||||
|
||||
# This must be present or the Salt loader won't load this module.
|
||||
__proxyenabled__ = ['panos']
|
||||
|
||||
# Variables are scoped to this module so we can have persistent data.
|
||||
GRAINS_CACHE = {'vendor': 'Palo Alto'}
|
||||
DETAILS = {}
|
||||
|
||||
# Set up logging
|
||||
log = logging.getLogger(__file__)
|
||||
|
||||
# Define the module's virtual name
|
||||
__virtualname__ = 'panos'
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only return if all the modules are available.
|
||||
'''
|
||||
return __virtualname__
|
||||
|
||||
|
||||
def init(opts):
|
||||
'''
|
||||
This function gets called when the proxy starts up. For
|
||||
panos devices, a determination is made on the connection type
|
||||
and the appropriate connection details that must be cached.
|
||||
'''
|
||||
if 'host' not in opts['proxy']:
|
||||
log.critical('No \'host\' key found in pillar for this proxy.')
|
||||
return False
|
||||
if 'apikey' not in opts['proxy']:
|
||||
# If we do not have an apikey, we must have both a username and password
|
||||
if 'username' not in opts['proxy']:
|
||||
log.critical('No \'username\' key found in pillar for this proxy.')
|
||||
return False
|
||||
if 'password' not in opts['proxy']:
|
||||
log.critical('No \'passwords\' key found in pillar for this proxy.')
|
||||
return False
|
||||
|
||||
DETAILS['url'] = 'https://{0}/api/'.format(opts['proxy']['host'])
|
||||
|
||||
# Set configuration details
|
||||
DETAILS['host'] = opts['proxy']['host']
|
||||
if 'serial' in opts['proxy']:
|
||||
DETAILS['serial'] = opts['proxy'].get('serial')
|
||||
if 'apikey' in opts['proxy']:
|
||||
log.debug("Selected pan_key method for panos proxy module.")
|
||||
DETAILS['method'] = 'pan_key'
|
||||
DETAILS['apikey'] = opts['proxy'].get('apikey')
|
||||
else:
|
||||
log.debug("Selected pan_pass method for panos proxy module.")
|
||||
DETAILS['method'] = 'pan_pass'
|
||||
DETAILS['username'] = opts['proxy'].get('username')
|
||||
DETAILS['password'] = opts['proxy'].get('password')
|
||||
else:
|
||||
if 'apikey' in opts['proxy']:
|
||||
log.debug("Selected dev_key method for panos proxy module.")
|
||||
DETAILS['method'] = 'dev_key'
|
||||
DETAILS['apikey'] = opts['proxy'].get('apikey')
|
||||
else:
|
||||
log.debug("Selected dev_pass method for panos proxy module.")
|
||||
DETAILS['method'] = 'dev_pass'
|
||||
DETAILS['username'] = opts['proxy'].get('username')
|
||||
DETAILS['password'] = opts['proxy'].get('password')
|
||||
|
||||
# Ensure connectivity to the device
|
||||
log.debug("Attempting to connect to panos proxy host.")
|
||||
query = {'type': 'op', 'cmd': '<show><system><info></info></system></show>'}
|
||||
call(query)
|
||||
log.debug("Successfully connected to panos proxy host.")
|
||||
|
||||
DETAILS['initialized'] = True
|
||||
|
||||
|
||||
def call(payload=None):
|
||||
'''
|
||||
This function captures the query string and sends it to the Palo Alto device.
|
||||
'''
|
||||
ret = {}
|
||||
try:
|
||||
if DETAILS['method'] == 'dev_key':
|
||||
# Pass the api key without the target declaration
|
||||
conditional_payload = {'key': DETAILS['apikey']}
|
||||
payload.update(conditional_payload)
|
||||
r = __utils__['http.query'](DETAILS['url'],
|
||||
data=payload,
|
||||
method='POST',
|
||||
decode_type='xml',
|
||||
decode=True,
|
||||
verify_ssl=False,
|
||||
raise_error=True)
|
||||
ret = r['dict'][0]
|
||||
elif DETAILS['method'] == 'dev_pass':
|
||||
# Pass credentials without the target declaration
|
||||
r = __utils__['http.query'](DETAILS['url'],
|
||||
username=DETAILS['username'],
|
||||
password=DETAILS['password'],
|
||||
data=payload,
|
||||
method='POST',
|
||||
decode_type='xml',
|
||||
decode=True,
|
||||
verify_ssl=False,
|
||||
raise_error=True)
|
||||
ret = r['dict'][0]
|
||||
elif DETAILS['method'] == 'pan_key':
|
||||
# Pass the api key with the target declaration
|
||||
conditional_payload = {'key': DETAILS['apikey'],
|
||||
'target': DETAILS['serial']}
|
||||
payload.update(conditional_payload)
|
||||
r = __utils__['http.query'](DETAILS['url'],
|
||||
data=payload,
|
||||
method='POST',
|
||||
decode_type='xml',
|
||||
decode=True,
|
||||
verify_ssl=False,
|
||||
raise_error=True)
|
||||
ret = r['dict'][0]
|
||||
elif DETAILS['method'] == 'pan_pass':
|
||||
# Pass credentials with the target declaration
|
||||
conditional_payload = {'target': DETAILS['serial']}
|
||||
payload.update(conditional_payload)
|
||||
r = __utils__['http.query'](DETAILS['url'],
|
||||
username=DETAILS['username'],
|
||||
password=DETAILS['password'],
|
||||
data=payload,
|
||||
method='POST',
|
||||
decode_type='xml',
|
||||
decode=True,
|
||||
verify_ssl=False,
|
||||
raise_error=True)
|
||||
ret = r['dict'][0]
|
||||
except KeyError as err:
|
||||
raise salt.exceptions.CommandExecutionError("Did not receive a valid response from host.")
|
||||
return ret
|
||||
|
||||
|
||||
def is_required_version(required_version='0.0.0'):
|
||||
'''
|
||||
Because different versions of Palo Alto support different command sets, this function
|
||||
will return true if the current version of Palo Alto supports the required command.
|
||||
'''
|
||||
if 'sw-version' in DETAILS['grains_cache']:
|
||||
current_version = DETAILS['grains_cache']['sw-version']
|
||||
else:
|
||||
# If we do not have the current sw-version cached, we cannot check version requirements.
|
||||
return False
|
||||
|
||||
required_version_split = required_version.split(".")
|
||||
current_version_split = current_version.split(".")
|
||||
|
||||
try:
|
||||
if int(current_version_split[0]) > int(required_version_split[0]):
|
||||
return True
|
||||
elif int(current_version_split[0]) < int(required_version_split[0]):
|
||||
return False
|
||||
|
||||
if int(current_version_split[1]) > int(required_version_split[1]):
|
||||
return True
|
||||
elif int(current_version_split[1]) < int(required_version_split[1]):
|
||||
return False
|
||||
|
||||
if int(current_version_split[2]) > int(required_version_split[2]):
|
||||
return True
|
||||
elif int(current_version_split[2]) < int(required_version_split[2]):
|
||||
return False
|
||||
|
||||
# We have an exact match
|
||||
return True
|
||||
except Exception as err:
|
||||
return False
|
||||
|
||||
|
||||
def initialized():
|
||||
'''
|
||||
Since grains are loaded in many different places and some of those
|
||||
places occur before the proxy can be initialized, return whether
|
||||
our init() function has been called
|
||||
'''
|
||||
return DETAILS.get('initialized', False)
|
||||
|
||||
|
||||
def grains():
|
||||
'''
|
||||
Get the grains from the proxied device
|
||||
'''
|
||||
if not DETAILS.get('grains_cache', {}):
|
||||
DETAILS['grains_cache'] = GRAINS_CACHE
|
||||
try:
|
||||
query = {'type': 'op', 'cmd': '<show><system><info></info></system></show>'}
|
||||
DETAILS['grains_cache'] = call(query)['system']
|
||||
except Exception as err:
|
||||
pass
|
||||
return DETAILS['grains_cache']
|
||||
|
||||
|
||||
def grains_refresh():
|
||||
'''
|
||||
Refresh the grains from the proxied device
|
||||
'''
|
||||
DETAILS['grains_cache'] = None
|
||||
return grains()
|
||||
|
||||
|
||||
def ping():
|
||||
'''
|
||||
Returns true if the device is reachable, else false.
|
||||
'''
|
||||
try:
|
||||
query = {'type': 'op', 'cmd': '<show><system><info></info></system></show>'}
|
||||
if 'result' in call(query)['system']:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except Exception as err:
|
||||
return False
|
||||
|
||||
|
||||
def shutdown():
|
||||
'''
|
||||
Shutdown the connection to the proxy device. For this proxy,
|
||||
shutdown is a no-op.
|
||||
'''
|
||||
log.debug('Panos proxy shutdown() called.')
|
579
salt/states/panos.py
Normal file
579
salt/states/panos.py
Normal file
@ -0,0 +1,579 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
A state module to manage Palo Alto network devices.
|
||||
|
||||
:codeauthor: :email:`Spencer Ervin <spencer_ervin@hotmail.com>`
|
||||
:maturity: new
|
||||
:depends: none
|
||||
:platform: unix
|
||||
|
||||
|
||||
About
|
||||
=====
|
||||
This state module was designed to handle connections to a Palo Alto based
|
||||
firewall. This module relies on the Palo Alto proxy module to interface with the devices.
|
||||
|
||||
This state module is designed to give extreme flexibility in the control over XPATH values on the PANOS device. It
|
||||
exposes the core XML API commands and allows state modules to chain complex XPATH commands.
|
||||
|
||||
Below is an example of how to construct a security rule and move to the top of the policy. This will take a config
|
||||
lock to prevent execution during the operation, then remove the lock. After the XPATH has been deployed, it will
|
||||
commit to the device.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/takelock:
|
||||
panos.add_config_lock
|
||||
panos/service_tcp_22:
|
||||
panos.set_config:
|
||||
- xpath: /config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/service
|
||||
- value: <entry name='tcp-22'><protocol><tcp><port>22</port></tcp></protocol></entry>
|
||||
- commit: False
|
||||
panos/create_rule1:
|
||||
panos.set_config:
|
||||
- xpath: /config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/security/rules
|
||||
- value: '
|
||||
<entry name="rule1">
|
||||
<from><member>trust</member></from>
|
||||
<to><member>untrust</member></to>
|
||||
<source><member>10.0.0.1</member></source>
|
||||
<destination><member>10.0.1.1</member></destination>
|
||||
<service><member>tcp-22</member></service>
|
||||
<application><member>any</member></application>
|
||||
<action>allow</action>
|
||||
<disabled>no</disabled>
|
||||
</entry>'
|
||||
- commit: False
|
||||
panos/moveruletop:
|
||||
panos.move_config:
|
||||
- xpath: /config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='rule1']
|
||||
- where: top
|
||||
- commit: False
|
||||
panos/removelock:
|
||||
panos.remove_config_lock
|
||||
panos/commit:
|
||||
panos.commit
|
||||
|
||||
.. seealso::
|
||||
:prox:`Palo Alto Proxy Module <salt.proxy.panos>`
|
||||
|
||||
'''
|
||||
|
||||
# Import Python Libs
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
return 'panos.commit' in __salt__
|
||||
|
||||
|
||||
def _default_ret(name):
|
||||
'''
|
||||
Set the default response values.
|
||||
|
||||
'''
|
||||
ret = {
|
||||
'name': name,
|
||||
'changes': {},
|
||||
'commit': None,
|
||||
'result': False,
|
||||
'comment': ''
|
||||
}
|
||||
return ret
|
||||
|
||||
|
||||
def add_config_lock(name):
|
||||
'''
|
||||
Prevent other users from changing configuration until the lock is released.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/takelock:
|
||||
panos.add_config_lock
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
ret.update({
|
||||
'changes': __salt__['panos.add_config_lock'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def clone_config(name, xpath=None, newname=None, commit=False):
|
||||
'''
|
||||
Clone a specific XPATH and set it to a new name.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
xpath(str): The XPATH of the configuration API tree to clone.
|
||||
|
||||
newname(str): The new name of the XPATH clone.
|
||||
|
||||
commit(bool): If true the firewall will commit the changes, if false do not commit changes.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/clonerule:
|
||||
panos.clone_config:
|
||||
- xpath: /config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules&from=/config/devices/
|
||||
entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='rule1']
|
||||
- value: rule2
|
||||
- commit: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if not xpath:
|
||||
return ret
|
||||
|
||||
if not newname:
|
||||
return ret
|
||||
|
||||
query = {'type': 'config',
|
||||
'action': 'clone',
|
||||
'xpath': xpath,
|
||||
'newname': newname}
|
||||
|
||||
response = __proxy__['panos.call'](query)
|
||||
|
||||
ret.update({
|
||||
'changes': response,
|
||||
'result': True
|
||||
})
|
||||
|
||||
if commit is True:
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def commit(name):
|
||||
'''
|
||||
Commits the candidate configuration to the running configuration.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/commit:
|
||||
panos.commit
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def delete_config(name, xpath=None, commit=False):
|
||||
'''
|
||||
Deletes a Palo Alto XPATH to a specific value.
|
||||
|
||||
Use the xpath parameter to specify the location of the object to be deleted.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
xpath(str): The XPATH of the configuration API tree to control.
|
||||
|
||||
commit(bool): If true the firewall will commit the changes, if false do not commit changes.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/deletegroup:
|
||||
panos.delete_config:
|
||||
- xpath: /config/devices/entry/vsys/entry[@name='vsys1']/address-group/entry[@name='test']
|
||||
- commit: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if not xpath:
|
||||
return ret
|
||||
|
||||
query = {'type': 'config',
|
||||
'action': 'delete',
|
||||
'xpath': xpath}
|
||||
|
||||
response = __proxy__['panos.call'](query)
|
||||
|
||||
ret.update({
|
||||
'changes': response,
|
||||
'result': True
|
||||
})
|
||||
|
||||
if commit is True:
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def download_software(name, version=None, synch=False, check=False):
|
||||
'''
|
||||
Ensures that a software version is downloaded.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
version(str): The software version to check. If this version is not already downloaded, it will attempt to download
|
||||
the file from Palo Alto.
|
||||
|
||||
synch(bool): If true, after downloading the file it will be synched to its peer.
|
||||
|
||||
check(bool): If true, the PANOS device will first attempt to pull the most recent software inventory list from Palo
|
||||
Alto.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/version8.0.0:
|
||||
panos.download_software:
|
||||
- version: 8.0.0
|
||||
- synch: False
|
||||
- check: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if check is True:
|
||||
__salt__['panos.check_software']()
|
||||
|
||||
versions = __salt__['panos.get_software_info']()
|
||||
|
||||
if 'sw-updates' not in versions \
|
||||
or 'versions' not in versions['sw-updates'] \
|
||||
or 'entry' not in versions['sw-updates']['versions']:
|
||||
ret.update({
|
||||
'comment': 'Software version is not found in the local software list.',
|
||||
'result': False
|
||||
})
|
||||
return ret
|
||||
|
||||
for entry in versions['sw-updates']['versions']['entry']:
|
||||
if entry['version'] == version and entry['downloaded'] == "yes":
|
||||
ret.update({
|
||||
'comment': 'Software version is already downloaded.',
|
||||
'result': True
|
||||
})
|
||||
return ret
|
||||
|
||||
ret.update({
|
||||
'changes': __salt__['panos.download_software_version'](version=version, synch=synch)
|
||||
})
|
||||
|
||||
versions = __salt__['panos.get_software_info']()
|
||||
|
||||
if 'sw-updates' not in versions \
|
||||
or 'versions' not in versions['sw-updates'] \
|
||||
or 'entry' not in versions['sw-updates']['versions']:
|
||||
ret.update({
|
||||
'result': False
|
||||
})
|
||||
return ret
|
||||
|
||||
for entry in versions['sw-updates']['versions']['entry']:
|
||||
if entry['version'] == version and entry['downloaded'] == "yes":
|
||||
ret.update({
|
||||
'result': True
|
||||
})
|
||||
return ret
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def edit_config(name, xpath=None, value=None, commit=False):
|
||||
'''
|
||||
Edits a Palo Alto XPATH to a specific value. This will always overwrite the existing value, even if it is not
|
||||
changed.
|
||||
|
||||
You can replace an existing object hierarchy at a specified location in the configuration with a new value. Use
|
||||
the xpath parameter to specify the location of the object, including the node to be replaced.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
xpath(str): The XPATH of the configuration API tree to control.
|
||||
|
||||
value(str): The XML value to edit. This must be a child to the XPATH.
|
||||
|
||||
commit(bool): If true the firewall will commit the changes, if false do not commit changes.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/addressgroup:
|
||||
panos.edit_config:
|
||||
- xpath: /config/devices/entry/vsys/entry[@name='vsys1']/address-group/entry[@name='test']
|
||||
- value: <static><entry name='test'><member>abc</member><member>xyz</member></entry></static>
|
||||
- commit: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if not xpath:
|
||||
return ret
|
||||
|
||||
if not value:
|
||||
return ret
|
||||
|
||||
query = {'type': 'config',
|
||||
'action': 'edit',
|
||||
'xpath': xpath,
|
||||
'element': value}
|
||||
|
||||
response = __proxy__['panos.call'](query)
|
||||
|
||||
ret.update({
|
||||
'changes': response,
|
||||
'result': True
|
||||
})
|
||||
|
||||
if commit is True:
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def move_config(name, xpath=None, where=None, dst=None, commit=False):
|
||||
'''
|
||||
Moves a XPATH value to a new location.
|
||||
|
||||
Use the xpath parameter to specify the location of the object to be moved, the where parameter to
|
||||
specify type of move, and dst parameter to specify the destination path.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
xpath(str): The XPATH of the configuration API tree to move.
|
||||
|
||||
where(str): The type of move to execute. Valid options are after, before, top, bottom. The after and before
|
||||
options will require the dst option to specify the destination of the action. The top action will move the
|
||||
XPATH to the top of its structure. The botoom action will move the XPATH to the bottom of its structure.
|
||||
|
||||
dst(str): Optional. Specifies the destination to utilize for a move action. This is ignored for the top
|
||||
or bottom action.
|
||||
|
||||
commit(bool): If true the firewall will commit the changes, if false do not commit changes.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/moveruletop:
|
||||
panos.move_config:
|
||||
- xpath: /config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='rule1']
|
||||
- where: top
|
||||
- commit: True
|
||||
|
||||
panos/moveruleafter:
|
||||
panos.move_config:
|
||||
- xpath: /config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security/rules/entry[@name='rule1']
|
||||
- where: after
|
||||
- dst: rule2
|
||||
- commit: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if not xpath:
|
||||
return ret
|
||||
|
||||
if not where:
|
||||
return ret
|
||||
|
||||
if where == 'after':
|
||||
query = {'type': 'config',
|
||||
'action': 'move',
|
||||
'xpath': xpath,
|
||||
'where': 'after',
|
||||
'dst': dst}
|
||||
elif where == 'before':
|
||||
query = {'type': 'config',
|
||||
'action': 'move',
|
||||
'xpath': xpath,
|
||||
'where': 'before',
|
||||
'dst': dst}
|
||||
elif where == 'top':
|
||||
query = {'type': 'config',
|
||||
'action': 'move',
|
||||
'xpath': xpath,
|
||||
'where': 'top'}
|
||||
elif where == 'bottom':
|
||||
query = {'type': 'config',
|
||||
'action': 'move',
|
||||
'xpath': xpath,
|
||||
'where': 'bottom'}
|
||||
|
||||
response = __proxy__['panos.call'](query)
|
||||
|
||||
ret.update({
|
||||
'changes': response,
|
||||
'result': True
|
||||
})
|
||||
|
||||
if commit is True:
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def remove_config_lock(name):
|
||||
'''
|
||||
Release config lock previously held.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/takelock:
|
||||
panos.remove_config_lock
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
ret.update({
|
||||
'changes': __salt__['panos.remove_config_lock'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def rename_config(name, xpath=None, newname=None, commit=False):
|
||||
'''
|
||||
Rename a Palo Alto XPATH to a specific value. This will always rename the value even if a change is not needed.
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
xpath(str): The XPATH of the configuration API tree to control.
|
||||
|
||||
newname(str): The new name of the XPATH value.
|
||||
|
||||
commit(bool): If true the firewall will commit the changes, if false do not commit changes.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/renamegroup:
|
||||
panos.rename_config:
|
||||
- xpath: /config/devices/entry/vsys/entry[@name='vsys1']/address/entry[@name='old_address']
|
||||
- value: new_address
|
||||
- commit: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if not xpath:
|
||||
return ret
|
||||
|
||||
if not newname:
|
||||
return ret
|
||||
|
||||
query = {'type': 'config',
|
||||
'action': 'rename',
|
||||
'xpath': xpath,
|
||||
'newname': newname}
|
||||
|
||||
response = __proxy__['panos.call'](query)
|
||||
|
||||
ret.update({
|
||||
'changes': response,
|
||||
'result': True
|
||||
})
|
||||
|
||||
if commit is True:
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def set_config(name, xpath=None, value=None, commit=False):
|
||||
'''
|
||||
Sets a Palo Alto XPATH to a specific value. This will always overwrite the existing value, even if it is not
|
||||
changed.
|
||||
|
||||
You can add or create a new object at a specified location in the configuration hierarchy. Use the xpath parameter
|
||||
to specify the location of the object in the configuration
|
||||
|
||||
name: The name of the module function to execute.
|
||||
|
||||
xpath(str): The XPATH of the configuration API tree to control.
|
||||
|
||||
value(str): The XML value to set. This must be a child to the XPATH.
|
||||
|
||||
commit(bool): If true the firewall will commit the changes, if false do not commit changes.
|
||||
|
||||
SLS Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
panos/hostname:
|
||||
panos.set_config:
|
||||
- xpath: /config/devices/entry[@name='localhost.localdomain']/deviceconfig/system
|
||||
- value: <hostname>foobar</hostname>
|
||||
- commit: True
|
||||
|
||||
'''
|
||||
ret = _default_ret(name)
|
||||
|
||||
if not xpath:
|
||||
return ret
|
||||
|
||||
if not value:
|
||||
return ret
|
||||
|
||||
query = {'type': 'config',
|
||||
'action': 'set',
|
||||
'xpath': xpath,
|
||||
'element': value}
|
||||
|
||||
response = __proxy__['panos.call'](query)
|
||||
|
||||
ret.update({
|
||||
'changes': response,
|
||||
'result': True
|
||||
})
|
||||
|
||||
if commit is True:
|
||||
ret.update({
|
||||
'commit': __salt__['panos.commit'](),
|
||||
'result': True
|
||||
})
|
||||
|
||||
return ret
|
Loading…
Reference in New Issue
Block a user