def get_device_groups_from_panorama(): xapi = panorama_login() device_group_xpath = "/config/devices/entry[@name='localhost.localdomain']/device-group" services = list() if xapi is None: print('Could not login to Panorama') return services try: xapi.get(device_group_xpath) xml = xapi.xml_result() except pan.xapi.PanXapiError as pxe: print('Could not get device groups from Panorama') print(pxe) return services if xml is None: print('No services currently defined in panorama') return services doc = et.fromstring(xml) for dg in doc: if 'name' in dg.attrib: service = dict() for tag in dg.findall('./tag/entry'): if 'name' in tag.attrib and ':' in tag.attrib['name']: k, v = tag.attrib['name'].split(':') service[k] = v service['name'] = dg.attrib['name'] services.append(service) return services
def print_response(xapi, options): if options['print_xml']: if options['print_result']: s = xapi.xml_result() else: s = xapi.xml_root() if s is not None: print(s) if options['print_python'] or options['print_json']: if options['print_result']: if (xapi.element_result is None or not len(xapi.element_result)): return elem = list(xapi.element_result)[0] else: if xapi.element_root is None: return elem = xapi.element_root try: conf = pan.config.PanConfig(config=elem) except pan.config.PanConfigError as msg: print('pan.config.PanConfigError:', msg, file=sys.stderr) sys.exit(1) d = conf.python() if d: if options['print_python']: print('var1 =', pprint.pformat(d)) if options['print_json']: print(json.dumps(d, sort_keys=True, indent=2))
def get_device_groups_from_panorama() -> list: """ Return a list of device groups from panorama instance :return: List of dicts containing device group entries """ xapi = panos_login() device_group_xpath = "/config/devices/entry[@name='localhost.localdomain']/device-group" services = list() try: xapi.get(device_group_xpath) xml = xapi.xml_result() except pan.xapi.PanXapiError as pxe: print('Could not get device groups from Panorama') print(pxe) return services doc = elementTree.fromstring(xml) for dg in doc: if 'name' in dg.attrib: service = dict() for tag in dg.findall('./tag/entry'): if 'name' in tag.attrib and ':' in tag.attrib['name']: k, v = tag.attrib['name'].split(':') service[k] = v service['name'] = dg.attrib['name'] services.append(service) return services
def test_panorama() -> None: """ test PAN-OS device auth from environment variables :return: None """ xapi = panos_login() xapi.op(cmd='show system info', cmd_xml=True) print(xapi.xml_result())
def test_panorama(): xapi = panorama_login() if xapi is None: print('Could not test Panorama') return None xapi.op(cmd='show system info', cmd_xml=True) print(xapi.xml_result())
def perform_backup() -> str: """ Saves a named backup on the PAN-OS device. The format for the backup is 'panhandler-20190424000000.xml' :return: xml results from the op command sequence """ xapi = panos_login() d = datetime.datetime.today() tstamp = d.strftime('%Y%m%d%H%M%S') cmd = f'<save><config><to>panhandler-{tstamp}.xml</to></config></save>' try: xapi.op(cmd=cmd) return xapi.xml_result() except pan.xapi.PanXapiError as pxe: raise TargetConnectionException(f'Could not perform backup: {pxe}')
def push_service(service, context): xapi = panorama_login() snippets_dir = Path(os.path.join(settings.BASE_DIR, 'mssp', 'snippets')) if xapi is None: print('Could not push service to Panorama') return False try: for snippet in service['snippets']: xpath = snippet['xpath'] xml_file_name = snippet['file'] xml_full_path = os.path.join(snippets_dir, service['name'], xml_file_name) with open(xml_full_path, 'r') as xml_file: xml_string = xml_file.read() xml_template = Environment( loader=BaseLoader()).from_string(xml_string) xpath_template = Environment( loader=BaseLoader()).from_string(xpath) xml_snippet = xml_template.render(context).replace('\n', '') xpath_string = xpath_template.render(context) print('Pushing xpath: %s' % xpath_string) #print('Pushing element: %s' % xml_snippet) xapi.set(xpath=xpath_string, element=xml_snippet) # FIXME - We need to fix this if xapi.status_code == '19' or xapi.status_code == '20': print('xpath is already present') elif xapi.status_code == '7': print('xpath was NOT found') return False xapi.commit('<commit/>', sync=True) print(xapi.xml_result()) return True except IOError as ioe: print('Could not open xml snippet file for reading!!!') # FIXME - raise a decent error here return False except pan.xapi.PanXapiError as pxe: print('Could not push service snippet!') print(pxe) return False
def print_response(xapi, options): if options['print_xml']: if options['print_result']: s = xapi.xml_result() else: s = xapi.xml_root() if s is not None: print(s.lstrip('\r\n').rstrip()) if options['print_python'] or options['print_json']: d = xml_python(xapi, options['print_result']) if d: if options['print_python']: print('var1 =', pprint.pformat(d)) if options['print_json']: print(json.dumps(d, sort_keys=True, indent=2)) if options['print_text'] and xapi.text_document is not None: print(xapi.text_document, end='')
def print_response(xapi, options): if options['print_xml']: if options['print_result']: s = xapi.xml_result() else: s = xapi.xml_root() if s is not None: print(s) if options['print_python'] or options['print_json']: d = xml_python(xapi, options['print_result']) if d: if options['print_python']: print('var1 =', pprint.pformat(d)) if options['print_json']: print(json.dumps(d, sort_keys=True, indent=2)) if options['print_text'] and xapi.text_document is not None: print(xapi.text_document, end='')
def get_response(xapi): if options['print_xml']: if options['print_result']: s = xapi.xml_result() else: s = xapi.xml_root() if s is not None: return s.lstrip('\r\n').rstrip() if options['print_python'] or options['print_json']: d = xml_python(xapi, options['print_result']) if d: if options['print_python']: return 'var1 =', pprint.pformat(d) if options['print_json']: return json.dumps(d, sort_keys=True, indent=2) if options['print_text'] and xapi.text_document is not None: return xapi.text_document
def check_job(xapi, jobnum, timeout=240): now = time.time() while time.time() < now + timeout: xapi.op(cmd='<show><jobs><id>%s</id></jobs></show>' % jobnum) print('result = {}'.format(xapi.xml_result())) status = xapi.element_root.find('.//status') if status is None: raise JobException("Invalid job %s: no status information %s" % (jobnum, xapi.xml_document)) if status.text == 'FIN': result = xapi.element_root.find('.//job/result') if result is None: raise JobException("Invalid FIN job %s: no result %s" % (jobnum, xapi.xml_document)) if result.text != 'OK': raise JobException("Job %s failed: %s" % (jobnum, xapi.xml_document)) return None raise JobException("Timeout in job %s" % jobnum)
def main(): parser = argparse.ArgumentParser( description= """Export current threat content from firewall or Panorama.""") parser.add_argument("-k", "--api_key", help="API key to use for connection.") required = parser.add_argument_group() required.add_argument("hostname", help="Hostname of firewall or Panorama") required.add_argument("output_file", help="Output file for report") args = parser.parse_args() output = None try: if args.api_key: xapi = pan.xapi.PanXapi(hostname=args.hostname, api_key=args.api_key) else: username = input("Username: "******"Password: "******"<show><predefined><xpath>/predefined/threats/vulnerability</xpath></predefined></show>" ) output = xapi.xml_result() except pan.xapi.PanXapiError as e: print("XML-API Error: {0}".format(e)) sys.exit(1) vulns = parse_xml(output) excel_output(args.output_file, vulns)
def print_response(xapi, options): if options['print_xml']: if options['print_result']: s = xapi.xml_result() else: s = xapi.xml_root() if s is not None: print(s) if options['print_python'] or options['print_json']: try: d = xapi.xml_python(options['print_result']) except pan.xapi.PanXapiError as msg: print('pan.xapi.PanXapi:', msg, file=sys.stderr) sys.exit(1) if d: if options['print_python']: print('var1 =', pprint.pformat(d)) if options['print_json']: print(json.dumps(d, sort_keys=True, indent=2))
def _set_command(self, command, cmd_xml, hostname, tag, pattern): result = False xapi = pan.xapi.PanXapi(**self._get_pan_credentials(hostname)) print( 'Running command on {hostname} with user {username} and password {password}...' .format(hostname=hostname, username=self.username, password=self.password[:1])) try: xapi.op(cmd=command, cmd_xml=cmd_xml) except pan.xapi.PanXapiError as e: print("{error}".format(error=e)) return False if xapi.status == 'success': soup = BeautifulSoup(xapi.xml_result(), 'html.parser') for line in soup.find_all(tag): result = line.get_text() print(result) if pattern: result = self._parso(pattern, result) return result
def get_vm_auth_key_from_panorama() -> str: """ Queries a Panorama instance to generate a new VM Auth key :return: string results from panorama (still needs parsed to pull out raw auth key) """ xapi = panos_login() if xapi is None: print('Could not login into PAN-OS target') raise TargetConnectionException try: xapi.op(cmd='<request><bootstrap><vm-auth-key><generate>' '<lifetime>24</lifetime></generate></vm-auth-key></bootstrap></request>') # FIXME - check status code here and do the right thing print(xapi.status_code) print(xapi.status_detail) return xapi.xml_result() except pan.xapi.PanXapiError as pxe: print('Could not get vm-auth-key!') print(pxe) raise TargetConnectionException
## https://hostname/api/?type=keygen&user=username&password=password user = '******' password = '' hostname = 'pa-200' keygen = False try: xapi = pan.xapi.PanXapi(tag=None, api_username=user, api_password=password, hostname=hostname) except pan.xapi.PanXapiError as msg: print('pan.xapi.PanXapi:', msg) sys.exit(1) xpath = "/config/devices/entry/vsys/entry/rulebase/security" xapi.show(xpath=xpath) s = xapi.xml_result() tree = ET.fromstring(s) for child in tree.iter('entry'): rule_name = child.get('name') nodes = child.findall('from') for node in nodes: from_int = node.find('member').text print rule_name, from_int #print(s.lstrip('\r\n').rstrip())
def main(): helper = get_connection( with_classic_provider_spec=True, argument_spec=dict( category=dict( default='configuration', choices=sorted(['configuration', 'certificate'] + HTML_EXPORTS + FILE_EXPORTS + [ 'application-pcap', 'filter-pcap', 'dlp-pcap', 'threat-pcap' ]), ), filename=dict(type='str'), certificate_name=dict(type='str'), certificate_format=dict(type='str', choices=['pem', 'pkcs10', 'pkcs12']), certificate_include_keys=dict(type='bool', default=False), certificate_passphrase=dict(type='str', no_log=True), application_pcap_name=dict(type='str'), dlp_pcap_name=dict(type='str'), dlp_password=dict(type='str', no_log=True), filter_pcap_name=dict(type='str'), threat_pcap_id=dict(type='str'), threat_pcap_search_time=dict(type='str'), threat_pcap_serial=dict(type='str'), timeout=dict(type='int', default=600), ), ) module = AnsibleModule(argument_spec=helper.argument_spec, supports_check_mode=False, required_one_of=helper.required_one_of, required_together=[ ['certificate_name', 'certificate_format'], ['dlp_pcap_name', 'dlp_password'], ]) if not HAS_LIB: module.fail_json( msg= 'pan-python, pandevice, and xmltodict are required for this module' ) category = module.params['category'] filename = module.params['filename'] timeout = module.params['timeout'] parent = helper.get_pandevice_parent(module) xapi = parent.xapi if category in (['configuration'] + HTML_EXPORTS): if filename is None: module.fail_json(msg='filename is required for export') export_text(module, xapi, category, filename) elif category in FILE_EXPORTS: if filename is None: module.fail_json(msg='filename is required for export') if category == 'stats-dump' and isinstance(parent, Panorama): module.fail_json(msg='stats-dump is not supported on Panorama') export_async(module, xapi, category, filename, timeout=timeout) elif category == 'certificate': if filename is None: module.fail_json(msg='filename is required for export') cert_name = module.params['certificate_name'] cert_format = module.params['certificate_format'] cert_include_keys = 'yes' if module.params[ 'certificate_include_keys'] else 'no' cert_passphrase = module.params['certificate_passphrase'] params = { 'certificate-name': cert_name, 'format': cert_format, 'include-key': cert_include_keys } if cert_include_keys == 'yes' and cert_passphrase is None: module.exit_json( msg= 'certificate_passphrase is required when certificate_include_keys is yes' ) if cert_passphrase is not None: params['passphrase'] = cert_passphrase xapi.export(category='certificate', extra_qs=params) export_binary(module, xapi, filename) elif category == 'application-pcap': # When exporting an application pcap, from_name can be: # - nothing, which gets you a list of directories # - a directory name, which gets you a list of pcaps in that directory # - a filename, which gets you the pcap file from_name = module.params['application_pcap_name'] xapi.export(category='application-pcap', from_name=from_name) if from_name is None or '.pcap' not in from_name: xml_result = xapi.xml_result() obj_dict = xmltodict.parse(xml_result) json_output = json.dumps(obj_dict) module.exit_json(changed=False, stdout=json_output, stdout_xml=xml_result) else: if filename is None: module.fail_json(msg='filename is required for export') export_binary(module, xapi, filename) elif category == 'filter-pcap': # When exporting a filter pcap, from_name can be: # - nothing, which gets you a list of files # - a filename, which gets you the pcap file from_name = module.params['filter_pcap_name'] xapi.export(category='filter-pcap', from_name=from_name) if from_name is None: xml_result = xapi.xml_result() obj_dict = xmltodict.parse(xml_result) json_output = json.dumps(obj_dict) module.exit_json(changed=False, stdout=json_output, stdout_xml=xml_result) else: if filename is None: module.fail_json(msg='filename is required for export') export_binary(module, xapi, filename) elif category == 'dlp-pcap': from_name = module.params['dlp_pcap_name'] dlp_password = module.params['dlp_password'] xapi.export(category='dlp-pcap', from_name=from_name, extra_qs={'dlp-password': dlp_password}) # When exporting a dlp pcap, from_name can be: # - nothing, which gets you a list of files # - a filename, which gets you the pcap file if from_name is None: xml_result = xapi.xml_result() obj_dict = xmltodict.parse(xml_result) json_output = json.dumps(obj_dict) module.exit_json(changed=False, stdout=json_output, stdout_xml=xml_result) else: if filename is None: module.fail_json(msg='filename is required for export') export_binary(module, xapi, filename) elif category == 'threat-pcap': if filename is None: module.fail_json(msg='filename is required for export') pcap_id = module.params['threat_pcap_id'] search_time = module.params['threat_pcap_search_time'] # pan-python says serial number is not required on certain PAN-OS releases (not required on 9.0 or 10.0) serial = module.params['threat_pcap_serial'] if isinstance(parent, Panorama) and serial is None: module.fail_json( msg='threat_pcap_serial is required when connecting to Panorama' ) xapi.export(category='threat-pcap', pcapid=pcap_id, search_time=search_time, serialno=serial) export_binary(module, xapi, filename) module.exit_json(changed=False)
import pan.xapi import xml.etree.ElementTree as ET import ipaddress import pprint import sys key="<>" hostname="panorama.domain.com" xapi = pan.xapi.PanXapi(api_key=key,hostname=hostname) xapi.op(cmd='show devices connected',cmd_xml=True) root_panorama = ET.fromstring(xapi.xml_result()) firewalls_number = len(root_panorama.findall('entry')) def progress(count, total, status=''): bar_len = 60 filled_len = int(round(bar_len * count / float(total))) percents = round(100.0 * count / float(total), 1) bar = '=' * filled_len + '-' * (bar_len - filled_len) sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', status)) sys.stdout.flush()
import logging ## To generate API key ## https://hostname/api/?type=keygen&user=username&password=password user = '******' password = '' hostname = 'pa-200' keygen = False try: xapi = pan.xapi.PanXapi(tag=None, api_username=user, api_password=password, hostname=hostname) except pan.xapi.PanXapiError as msg: print('pan.xapi.PanXapi:', msg) sys.exit(1) xpath = "/config/devices/entry/vsys/entry/rulebase/security" xapi.show(xpath=xpath) s = xapi.xml_result() tree = ET.fromstring(s) for child in tree.iter('entry'): rule_name = child.get('name') nodes = child.findall('from') for node in nodes: from_int = node.find('member').text print rule_name, from_int #print(s.lstrip('\r\n').rstrip())
print('pan.xapi.PanXapi:', msg) sys.exit(1) # estamos en modo "Panorama, asi que primero tenemos que buscar que FW hay cmd = "<show><devices><connected></connected></devices></show>" xpath = "/" try: connected = xapi.op(cmd=cmd, vsys=None, cmd_xml=False) except pan.xapi.PanXapiError as msg: print('edit:', msg) sys.exit(1) dodebug("OK se ejecuta el comando:" + cmd) #dodebug("result:\n"+xapi.xml_result()) pp = pprint.PrettyPrinter(indent=4) dict = xmltodict.parse(xapi.xml_result()) #pp.pprint(dict) dodebug("**** priting ddict['devices']['entry']") node = dict['devices']['entry'] #pp.pprint(node) hosts = [] for device in (node): serial = device['serial'] hostname = device['hostname'] ip4 = device['ip-address'] model = device['model'] dodebug(hostname + " " + model + " " + " " + ip4 + " " + serial) hosts.append(serial) ##OK ahora lo importante , tenemos: # mode el modo = panorama o firewall
def main(): helper = get_connection( with_classic_provider_spec=True, argument_spec=dict( category=dict( default="configuration", choices=sorted(["configuration", "certificate"] + HTML_EXPORTS + FILE_EXPORTS + ["device-state"] + [ "application-pcap", "filter-pcap", "dlp-pcap", "threat-pcap" ]), ), filename=dict(type="str"), certificate_name=dict(type="str"), certificate_format=dict(type="str", choices=["pem", "pkcs10", "pkcs12"]), certificate_include_keys=dict(type="bool", default=False), certificate_passphrase=dict(type="str", no_log=True), application_pcap_name=dict(type="str"), dlp_pcap_name=dict(type="str"), dlp_password=dict(type="str", no_log=True), filter_pcap_name=dict(type="str"), threat_pcap_id=dict(type="str"), threat_pcap_search_time=dict(type="str"), threat_pcap_serial=dict(type="str"), timeout=dict(type="int", default=600), ), ) module = AnsibleModule( argument_spec=helper.argument_spec, supports_check_mode=False, required_one_of=helper.required_one_of, required_together=[ ["certificate_name", "certificate_format"], ["dlp_pcap_name", "dlp_password"], ], ) if not HAS_LIB: module.fail_json( msg= "pan-python, pandevice, and xmltodict are required for this module" ) category = module.params["category"] filename = module.params["filename"] timeout = module.params["timeout"] parent = helper.get_pandevice_parent(module) xapi = parent.xapi if category in (["configuration"] + HTML_EXPORTS): if filename is None: module.fail_json(msg="filename is required for export") export_text(module, xapi, category, filename) elif category in FILE_EXPORTS: if filename is None: module.fail_json(msg="filename is required for export") if category == "stats-dump" and isinstance(parent, Panorama): module.fail_json(msg="stats-dump is not supported on Panorama") export_async(module, xapi, category, filename, timeout=timeout) elif category == "device-state": if filename is None: module.fail_json(msg="filename is required for export") export_binary(module, xapi, category, filename) elif category == "certificate": if filename is None: module.fail_json(msg="filename is required for export") cert_name = module.params["certificate_name"] cert_format = module.params["certificate_format"] cert_include_keys = "yes" if module.params[ "certificate_include_keys"] else "no" cert_passphrase = module.params["certificate_passphrase"] params = { "certificate-name": cert_name, "format": cert_format, "include-key": cert_include_keys, } if cert_include_keys == "yes" and cert_passphrase is None: module.exit_json( msg= "certificate_passphrase is required when certificate_include_keys is yes" ) if cert_passphrase is not None: params["passphrase"] = cert_passphrase xapi.export(category="certificate", extra_qs=params) export_binary(module, xapi, filename) elif category == "application-pcap": # When exporting an application pcap, from_name can be: # - nothing, which gets you a list of directories # - a directory name, which gets you a list of pcaps in that directory # - a filename, which gets you the pcap file from_name = module.params["application_pcap_name"] xapi.export(category="application-pcap", from_name=from_name) if from_name is None or ".pcap" not in from_name: xml_result = xapi.xml_result() obj_dict = xmltodict.parse(xml_result) json_output = json.dumps(obj_dict) module.exit_json(changed=False, stdout=json_output, stdout_xml=xml_result) else: if filename is None: module.fail_json(msg="filename is required for export") export_binary(module, xapi, filename) elif category == "filter-pcap": # When exporting a filter pcap, from_name can be: # - nothing, which gets you a list of files # - a filename, which gets you the pcap file from_name = module.params["filter_pcap_name"] xapi.export(category="filter-pcap", from_name=from_name) if from_name is None: xml_result = xapi.xml_result() obj_dict = xmltodict.parse(xml_result) json_output = json.dumps(obj_dict) module.exit_json(changed=False, stdout=json_output, stdout_xml=xml_result) else: if filename is None: module.fail_json(msg="filename is required for export") export_binary(module, xapi, filename) elif category == "dlp-pcap": from_name = module.params["dlp_pcap_name"] dlp_password = module.params["dlp_password"] xapi.export( category="dlp-pcap", from_name=from_name, extra_qs={"dlp-password": dlp_password}, ) # When exporting a dlp pcap, from_name can be: # - nothing, which gets you a list of files # - a filename, which gets you the pcap file if from_name is None: xml_result = xapi.xml_result() obj_dict = xmltodict.parse(xml_result) json_output = json.dumps(obj_dict) module.exit_json(changed=False, stdout=json_output, stdout_xml=xml_result) else: if filename is None: module.fail_json(msg="filename is required for export") export_binary(module, xapi, filename) elif category == "threat-pcap": if filename is None: module.fail_json(msg="filename is required for export") pcap_id = module.params["threat_pcap_id"] search_time = module.params["threat_pcap_search_time"] # pan-python says serial number is not required on certain PAN-OS releases (not required on 9.0 or 10.0) serial = module.params["threat_pcap_serial"] if isinstance(parent, Panorama) and serial is None: module.fail_json( msg="threat_pcap_serial is required when connecting to Panorama" ) xapi.export( category="threat-pcap", pcapid=pcap_id, search_time=search_time, serialno=serial, ) export_binary(module, xapi, filename) module.exit_json(changed=False)
description = ET.SubElement(entryAddress, "description") description.text = nodeID grpEntryStaticMember = ET.SubElement(grpEntryStatic, "member") grpEntryStaticMember.text = nodeID data = ET.tostring(root) print(data) try: xapi = pan.xapi.PanXapi(api_username=os.environ['username'], api_password=os.environ['password'], hostname=os.environ['ipAddr']) print("Successfully Connected!") xapi.op(cmd='show system info', cmd_xml=True) print(xapi.xml_result()) #set the config using the above xpath xapi.set(xpath, element=data) print(xapi.xml_result()) #commit the config. Make sure to add the xml command. xapi.commit('<commit/>') print(xapi.xml_result()) except pan.xapi.PanXapiError as msg: print('pan.xapi.PanXapi:', msg, file=sys.stderr) sys.exit(1) elif cmd == "stop":
def push_meta(meta, context, force_sync=False, perform_commit=True) -> (str, None): """ Push a skillet to a PanXapi connected device :param meta: dict containing parsed and loaded skillet :param context: all compiled variables from the user interaction :param force_sync: should we wait on a successful commit operation or return after queue :param perform_commit: should we actually commit or not :return: job_id as a str or None if no job_id could be found """ xapi = panos_login() if xapi is None: raise CCFParserError('Could not login in to Palo Alto Networks Device') name = meta['name'] if 'name' in meta else 'unknown' # default to None as return value, set to job_id if possible later if a commit was requested return_value = None # _perform_backup() if 'snippet_path' in meta: snippets_dir = meta['snippet_path'] else: raise CCFParserError(f'Could not locate .meta-cnc file on filesystem for Skillet: {name}') environment = Environment(loader=BaseLoader()) for f in jinja_filters.defined_filters: if hasattr(jinja_filters, f): environment.filters[f] = getattr(jinja_filters, f) try: for snippet in meta['snippets']: if 'xpath' not in snippet or 'file' not in snippet: print('Malformed meta-cnc error') raise CCFParserError(f'Malformed snippet section in meta-cnc file for {name}') xpath = snippet['xpath'] xml_file_name = snippet['file'] # allow snippets to be skipped using the 'when' attribute if 'when' in snippet: when_template = environment.from_string(snippet.get('when', '')) when_result = str(when_template.render(context)) if when_result.lower() == 'false' or when_result.lower() == 'no': print(f'Skipping snippet {name} due to when condition false') continue xml_full_path = os.path.join(snippets_dir, xml_file_name) with open(xml_full_path, 'r') as xml_file: xml_string = xml_file.read() xml_template = environment.from_string(xml_string) xpath_template = environment.from_string(xpath) # fix for #74, ensure multiline xpaths do not contain newlines or spaces xml_snippet = xml_template.render(context).strip().replace('\n', '') xpath_string = xpath_template.render(context).strip().replace('\n', '').replace(' ', '') print('Pushing xpath: %s' % xpath_string) try: xapi.set(xpath=xpath_string, element=xml_snippet) if xapi.status_code == '19' or xapi.status_code == '20': print('xpath is already present') elif xapi.status_code == '7': raise CCFParserError(f'xpath {xpath_string} was NOT found for skillet: {name}') except pan.xapi.PanXapiError as pxe: err_msg = str(pxe) if '403' in err_msg: # Auth issue, let's clear the api_key and bail out! xapi = None clear_credentials() raise CCFParserError(f'Could not push skillet {name} / snippet {xml_file_name}! {pxe}') if perform_commit: if 'type' not in meta: commit_type = 'commit' else: if 'panorama' in meta['type']: commit_type = 'commit-all' else: commit_type = 'commit' if commit_type == 'commit-all': print('Performing commit-all in panorama') xapi.commit(cmd='<commit-all></commit-all>', sync=True) else: if force_sync: xapi.commit('<commit></commit>', sync=True) else: xapi.commit('<commit></commit>') results = xapi.xml_result() if force_sync: # we have the results of a job id query, the commit results are embedded therein doc = elementTree.XML(results) embedded_result = doc.find('result') if embedded_result is not None: commit_result = embedded_result.text print(f'Commit result is {commit_result}') if commit_result == 'FAIL': raise TargetCommitException(xapi.status_detail) else: if 'with jobid' in results: result = re.match(r'.* with jobid (\d+)', results) if result is not None: return_value = result.group(1) # for gpcs baseline and svc connection network configuration do a scope push to gpcs # FIXME - check for 'gpcs' in meta['type'] instead of hardcoded name if meta['name'] == 'gpcs_baseline': print('push baseline and svc connection scope to gpcs') xapi.commit(action='all', cmd='<commit-all><template-stack>' '<name>Service_Conn_Template_Stack</name></template-stack></commit-all>') print(xapi.xml_result()) # for gpcs remote network configuration do a scope push to gpcs if meta['name'] == 'gpcs_remote' or meta['name'] == 'gpcs_baseline': print('push remote network scope to gpcs') xapi.commit(action='all', cmd='<commit-all><shared-policy><device-group>' '<entry name="Remote_Network_Device_Group"/>' '</device-group></shared-policy></commit-all>') print(xapi.xml_result()) return return_value except UndefinedError as ue: raise CCFParserError(f'Undefined variable in skillet: {ue}') except IOError as ioe: raise CCFParserError(f'Could not open xml snippet file for reading! {ioe}') except pan.xapi.PanXapiError as pxe: raise CCFParserError(f'Could not push meta-cnc for skillet {name}! {pxe}')