Panxapi para Python
Panxapi para Python
/usr/bin/env python
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
handler = logging.StreamHandler()
formatter = logging.Formatter(log_format)
handler.setFormatter(formatter)
logger.addHandler(handler)
if options['cafile'] or options['capath']:
ssl_context = create_ssl_context(options['cafile'],
options['capath'])
else:
ssl_context = None
try:
xapi = pan.xapi.PanXapi(timeout=options['timeout'],
tag=options['tag'],
use_http=options['use_http'],
use_get=options['use_get'],
api_username=options['api_username'],
api_password=options['api_password'],
api_key=options['api_key'],
hostname=options['hostname'],
port=options['port'],
serial=options['serial'],
ssl_context=ssl_context)
except pan.xapi.PanXapiError as msg:
print('pan.xapi.PanXapi:', msg, file=sys.stderr)
sys.exit(1)
if options['debug'] > 2:
print('xapi.__str__()===>\n', xapi, '\n<===',
sep='', file=sys.stderr)
extra_qs_used = False
try:
if options['keygen']:
action = 'keygen'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.keygen(extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if (options['api_username'] and options['api_password'] and
options['hostname'] and options['tag']):
# .panrc
d = datetime.now()
print('# %s generated: %s' % (os.path.basename(sys.argv[0]),
d.strftime('%Y/%m/%d %H:%M:%S')))
print('hostname%%%s=%s' % (options['tag'],
options['hostname']))
print('api_key%%%s=%s' % (options['tag'], xapi.api_key))
else:
print('API key: "%s"' % xapi.api_key)
if options['show']:
action = 'show'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.show(xpath=options['xpath'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['get']:
action = 'get'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.get(xpath=options['xpath'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['delete']:
action = 'delete'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.delete(xpath=options['xpath'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['edit']:
action = 'edit'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.edit(xpath=options['xpath'],
element=options['element'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['set']:
action = 'set'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.set(xpath=options['xpath'],
element=options['element'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['dynamic-update']:
action = 'dynamic-update'
kwargs = {
'cmd': options['cmd'],
}
if options['ad_hoc'] is not None:
extra_qs_used = True
kwargs['extra_qs'] = options['ad_hoc']
if len(options['vsys']):
kwargs['vsys'] = options['vsys'][0]
xapi.user_id(**kwargs)
print_status(xapi, action)
print_response(xapi, options)
if options['move'] is not None:
action = 'move'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.move(xpath=options['xpath'],
where=options['move'],
dst=options['dst'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['rename']:
action = 'rename'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.rename(xpath=options['xpath'],
newname=options['dst'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['clone']:
action = 'clone'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.clone(xpath=options['xpath'],
xpath_from=options['src'],
newname=options['dst'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['override']:
action = 'override'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.override(xpath=options['xpath'],
element=options['element'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['export'] is not None:
action = 'export'
if options['ad_hoc'] is not None:
extra_qs_used = True
if options['pcapid'] is not None:
xapi.export(category=options['export'],
pcapid=options['pcapid'],
search_time=options['stime'],
serialno=options['serial'],
extra_qs=options['ad_hoc'])
else:
xapi.export(category=options['export'],
from_name=options['src'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['pcap_listing']:
pcap_listing(xapi, options['export'])
save_attachment(xapi, options)
if options['log'] is not None:
action = 'log'
if options['ad_hoc'] is not None:
extra_qs_used = True
xapi.log(log_type=options['log'],
nlogs=options['nlogs'],
skip=options['skip'],
filter=options['filter'],
interval=options['interval'],
timeout=options['job_timeout'],
extra_qs=options['ad_hoc'])
print_status(xapi, action)
print_response(xapi, options)
if options['op'] is not None:
action = 'op'
kwargs = {
'cmd': options['op'],
'cmd_xml': options['cmd_xml'],
}
if options['ad_hoc'] is not None:
extra_qs_used = True
kwargs['extra_qs'] = options['ad_hoc']
if len(options['vsys']):
kwargs['vsys'] = options['vsys'][0]
xapi.op(**kwargs)
print_status(xapi, action)
print_response(xapi, options)
if (options['commit'] or options['commit_all']):
if options['cmd']:
cmd = options['cmd']
if options['cmd_xml']:
cmd = xapi.cmd_xml(cmd)
else:
c = pan.commit.PanCommit(validate=options['validate'],
force=options['force'],
commit_all=options['commit_all'],
merge_with_candidate=
options['merge'])
for part in options['partial']:
if part == 'device-and-network-excluded':
c.device_and_network_excluded()
elif part == 'policy-and-objects-excluded':
c.policy_and_objects_excluded()
elif part == 'shared-object-excluded':
c.shared_object_excluded()
elif part == 'no-vsys':
c.no_vsys()
elif part == 'vsys':
c.vsys(options['vsys'])
if options['serial'] is not None:
c.device(options['serial'])
if options['group'] is not None:
c.device_group(options['group'])
if options['commit_all'] and options['vsys']:
c.vsys(options['vsys'][0])
cmd = c.cmd()
kwargs = {
'cmd': cmd,
'sync': options['sync'],
'interval': options['interval'],
'timeout': options['job_timeout'],
}
if options['ad_hoc'] is not None:
extra_qs_used = True
kwargs['extra_qs'] = options['ad_hoc']
if options['commit_all']:
kwargs['action'] = 'all'
action = 'commit'
xapi.commit(**kwargs)
print_status(xapi, action)
print_response(xapi, options)
if not extra_qs_used and options['ad_hoc'] is not None:
action = 'ad_hoc'
xapi.ad_hoc(qs=options['ad_hoc'],
xpath=options['xpath'],
modify_qs=options['modify'])
print_status(xapi, action)
print_response(xapi, options)
except pan.xapi.PanXapiError as msg:
print_status(xapi, action, str(msg))
print_response(xapi, options)
sys.exit(1)
sys.exit(0)
def parse_opts():
options = {
'delete': False,
'edit': False,
'get': False,
'keygen': False,
'show': False,
'set': False,
'dynamic-update': False,
'commit': False,
'validate': False,
'force': False,
'partial': [],
'sync': False,
'vsys': [],
'commit_all': False,
'ad_hoc': None,
'modify': False,
'op': None,
'export': None,
'log': None,
'src': None,
'dst': None,
'move': None,
'rename': False,
'clone': False,
'override': False,
'api_username': None,
'api_password': None,
'hostname': None,
'port': None,
'serial': None,
'group': None,
'merge': False,
'nlogs': None,
'skip': None,
'filter': None,
'interval': None,
'job_timeout': None,
'stime': None,
'pcapid': None,
'api_key': None,
'cafile': None,
'capath': None,
'print_xml': False,
'print_result': False,
'print_python': False,
'print_json': False,
'print_text': False,
'cmd_xml': False,
'pcap_listing': False,
'recursive': False,
'use_http': False,
'use_get': False,
'debug': 0,
'tag': None,
'xpath': None,
'element': None,
'cmd': None,
'timeout': None,
}
valid_where = ['after', 'before', 'top', 'bottom']
short_options = 'de:gksS:U:C:A:o:l:h:P:K:xpjrXHGDt:T:'
long_options = ['version', 'help',
'ad-hoc=', 'modify', 'validate', 'force', 'partial=',
'sync', 'vsys=', 'src=', 'dst=', 'move=', 'rename',
'clone', 'override=', 'export=', 'log=', 'recursive',
'cafile=', 'capath=', 'ls', 'serial=',
'group=', 'merge', 'nlogs=', 'skip=', 'filter=',
'interval=', 'timeout=',
'stime=', 'pcapid=', 'text',
]
try:
opts, args = getopt.getopt(sys.argv[1:],
short_options,
long_options)
except getopt.GetoptError as error:
print(error, file=sys.stderr)
sys.exit(1)
for opt, arg in opts:
if opt == '-d':
options['delete'] = True
elif opt == '-e':
options['edit'] = True
options['element'] = get_element(arg)
elif opt == '-g':
options['get'] = True
elif opt == '-k':
options['keygen'] = True
elif opt == '-s':
options['show'] = True
elif opt == '-S':
options['set'] = True
options['element'] = get_element(arg)
elif opt == '-U':
options['dynamic-update'] = True
options['cmd'] = get_element(arg)
elif opt == '-C':
options['commit'] = True
options['cmd'] = get_element(arg)
elif opt == '--validate':
options['validate'] = True
elif opt == '--force':
options['force'] = True
elif opt == '--partial':
if arg:
l = get_parts(arg)
[options['partial'].append(s) for s in l]
elif opt == '--sync':
options['sync'] = True
elif opt == '--vsys':
if arg:
l = get_vsys(arg)
[options['vsys'].append(s) for s in l]
elif opt == '-A':
options['commit_all'] = True
options['cmd'] = get_element(arg)
elif opt == '--ad-hoc':
options['ad_hoc'] = arg
elif opt == '--modify':
options['modify'] = True
elif opt == '-o':
options['op'] = get_element(arg)
elif opt == '--export':
options['export'] = arg
elif opt == '--log':
options['log'] = arg
elif opt == '--src':
options['src'] = arg
elif opt == '--dst':
options['dst'] = arg
elif opt == '--move':
if arg not in valid_where:
print('Invalid where: "%s"' % arg, file=sys.stderr)
sys.exit(1)
options['move'] = arg
elif opt == '--rename':
options['rename'] = True
elif opt == '--clone':
options['clone'] = True
elif opt == '--override':
options['override'] = True
options['element'] = get_element(arg)
elif opt == '-l':
try:
(options['api_username'],
options['api_password']) = arg.split(':', 1)
except ValueError:
print('Invalid api_username:api_password: "%s"' %
arg, file=sys.stderr)
sys.exit(1)
elif opt == '-P':
options['port'] = arg
elif opt == '--serial':
options['serial'] = arg
elif opt == '--group':
options['group'] = arg
elif opt == '--merge':
options['merge'] = True
elif opt == '--nlogs':
options['nlogs'] = arg
elif opt == '--skip':
options['skip'] = arg
elif opt == '--filter':
options['filter'] = arg
elif opt == '--interval':
options['interval'] = arg
elif opt == '--timeout':
options['job_timeout'] = arg
elif opt == '--stime':
options['stime'] = arg
elif opt == '--pcapid':
options['pcapid'] = arg
elif opt == '-h':
options['hostname'] = arg
elif opt == '-K':
options['api_key'] = arg
elif opt == '--cafile':
options['cafile'] = arg
elif opt == '--capath':
options['capath'] = arg
elif opt == '-x':
options['print_xml'] = True
elif opt == '-p':
options['print_python'] = True
elif opt == '-j':
options['print_json'] = True
elif opt == '-r':
options['print_result'] = True
elif opt == '--text':
options['print_text'] = True
elif opt == '-X':
options['cmd_xml'] = True
elif opt == '--ls':
options['pcap_listing'] = True
elif opt == '--recursive':
options['recursive'] = True
elif opt == '-H':
options['use_http'] = True
elif opt == '-G':
options['use_get'] = True
elif opt == '-D':
if not options['debug'] < 3:
print('Maximum debug level is 3', file=sys.stderr)
sys.exit(1)
global debug
debug += 1
options['debug'] = debug
elif opt == '-t':
if arg:
options['tag'] = arg
elif opt == '-T':
options['timeout'] = arg
elif opt == '--version':
print('pan-python', pan.xapi.__version__)
sys.exit(0)
elif opt == '--help':
usage()
sys.exit(0)
else:
assert False, 'unhandled option %s' % opt
if len(args) > 0:
s = get_element(args.pop(0))
options['xpath'] = s.rstrip('\r\n')
if len(args) > 0:
print('Extra options after xpath:', args, file=sys.stderr)
if options['debug'] > 2:
s = pprint.pformat(options, indent=4)
print(s, file=sys.stderr)
if options['print_result'] and not (options['print_xml'] or
options['print_json'] or
options['print_python']):
options['print_xml'] = True
return options
def create_ssl_context(cafile, capath):
if (sys.version_info.major == 2 and sys.hexversion >= 0x02070900 or
sys.version_info.major == 3 and sys.hexversion >= 0x03020000):
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.options |= ssl.OP_NO_SSLv2
context.options |= ssl.OP_NO_SSLv3
context.verify_mode = ssl.CERT_REQUIRED
# added 3.4
if hasattr(context, 'check_hostname'):
context.check_hostname = True
try:
context.load_verify_locations(cafile=cafile, capath=capath)
except Exception as e:
print('cafile or capath invalid: %s' % e, file=sys.stderr)
sys.exit(1)
return context
print('Warning: Python %d.%d: cafile and capath ignored' %
(sys.version_info.major, sys.version_info.minor),
file=sys.stderr)
return None
def get_vsys(s):
list = []
vsys = s.split(',')
for v in vsys:
if v:
if v.isdigit():
list.append('vsys' + v)
else:
list.append(v)
return list
def get_parts(s):
list = []
parts = s.split(',')
for part in parts:
if part:
if not pan.commit.valid_part(part):
print('Invalid part: "%s"' % part, file=sys.stderr)
sys.exit(1)
list.append(part)
return list
def get_element(s):
stdin_char = '-'
if s == stdin_char:
element = sys.stdin.readlines()
elif os.path.isfile(s):
try:
f = open(s)
except IOError as msg:
print('open %s: %s' % (s, msg), file=sys.stderr)
sys.exit(1)
element = f.readlines()
f.close()
else:
element = s
element = ''.join(element)
if debug > 1:
print('element: \"%s\"' % element, file=sys.stderr)
return element
def print_status(xapi, action, exception_msg=None):
print(action, end='', file=sys.stderr)
if xapi.status_code is not None:
code = ' [code=\"%s\"]' % xapi.status_code
else:
code = ''
if xapi.status is not None:
print(': %s%s' % (xapi.status, code), end='', file=sys.stderr)
if exception_msg is not None and exception_msg:
print(': "%s"' % exception_msg.rstrip(), end='', file=sys.stderr)
elif xapi.status_detail is not None:
print(': "%s"' % xapi.status_detail.rstrip(), end='', file=sys.stderr)
print(file=sys.stderr)
def xml_python(xapi, result=False):
xpath = None
if result:
if (xapi.element_result is None or
not len(xapi.element_result)):
return None
elem = xapi.element_result
# select all child elements
xpath = '*'
else:
if xapi.element_root is None:
return None
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(xpath)
return d
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 save_attachment(xapi, options):
if xapi.export_result is None:
return
if options['src'] is not None:
# pcap
src_dir, src_file = os.path.split(options['src'])
else:
# 6.0 threat-pcap
# device-state
src_dir = None
src_file = xapi.export_result['file']
path = ''
path_done = False
if options['dst'] is not None:
path = options['dst']
if not os.path.isdir(path):
path_done = True
if not path_done:
if (options['recursive'] and src_dir and
re.search(r'^\d{8,8}$', src_dir)):
path = os.path.join(path, src_dir)
if not os.path.isdir(path):
try:
os.mkdir(path)
except OSError as msg:
print('mkdir %s: %s' % (path, msg),
file=sys.stderr)
# fallthrough, return on open fail
path = os.path.join(path, src_file)
try:
f = open(path, 'wb')
except IOError as msg:
print('open %s: %s' % (path, msg), file=sys.stderr)
return
try:
f.write(xapi.export_result['content'])
except IOError as msg:
print('write %s: %s' % (path, msg), file=sys.stderr)
f.close()
return
f.close()
print('exported %s: %s' % (xapi.export_result['category'], path),
file=sys.stderr)
def pcap_listing(xapi, category):
d = xml_python(xapi, result=True)
if d and 'dir-listing' in d:
pcap_listing = d['dir-listing']
if pcap_listing is None:
print('No %s directories' % category)
elif 'file' in pcap_listing:
file = pcap_listing['file']
if isinstance(file, str):
file = [file]
size = len(file)
print('%d %s files:' % (size, category))
for item in sorted(file):
print('
%s' % item)
elif 'dir' in pcap_listing:
dir = pcap_listing['dir']
if isinstance(dir, str):
dir = [dir]
size = len(dir)
def usage():
usage = '''%s [options] [xpath]
-d
delete object at xpath
-e element
edit XML element at xpath
-g
get candidate config at xpath
-k
generate API key
-s
show active config at xpath
-S element
set XML element at xpath
-U cmd
execute dynamic update command
-C cmd
commit candidate configuration
--validate
validate candidate configuration
--force
force commit when conflict
--partial part
commit specified part
--sync
synchronous commit
-A cmd
commit-all (Panorama)
--ad-hoc query
perform ad hoc request
--modify
insert known fields in ad hoc query
-o cmd
execute operational command
--export category
export files
--log log-type
retrieve log files
--src src
clone source node xpath
export source file/path/directory
--dst dst
move/clone destination node name
rename new name
export destination file/path/directory
--move where
move after, before, bottom or top
--rename
rename object at xpath to dst
--clone
--override element
--vsys vsys