def main(): # Get command line arguments parser = argparse.ArgumentParser( description= "Upgrade a Palo Alto Networks Firewall or Panorama to the specified version" ) parser.add_argument("-v", "--verbose", action="count", help="Verbose (-vv for extra verbose)") parser.add_argument("-q", "--quiet", action="store_true", help="No output") parser.add_argument( "-n", "--dryrun", action="store_true", help="Print what would happen, but don't perform upgrades", ) # Palo Alto Networks related arguments fw_group = parser.add_argument_group("Palo Alto Networks Device") fw_group.add_argument("hostname", help="Hostname of Firewall or Panorama") fw_group.add_argument("username", help="Username for Firewall or Panorama") fw_group.add_argument("password", help="Password for Firewall or Panorama") fw_group.add_argument( "version", help="The target PAN-OS/Panorama version (eg. 7.0.0 or latest)") args = parser.parse_args() ### Set up logger # Logging Levels # WARNING is 30 # INFO is 20 # DEBUG is 10 if args.verbose is None: args.verbose = 0 if not args.quiet: logging_level = 20 - (args.verbose * 10) if logging_level <= logging.DEBUG: logging_format = "%(levelname)s:%(name)s:%(message)s" else: logging_format = "%(message)s" logging.basicConfig(format=logging_format, level=logging_level) # Connect to the device and determine its type (Firewall or Panorama). # This is important to know what version to upgrade to next. device = PanDevice.create_from_device( args.hostname, args.username, args.password, ) # Perform the upgrades in sequence with reboots between each upgrade device.software.upgrade_to_version(args.version, args.dryrun)
def main(): # Get command line arguments parser = argparse.ArgumentParser( description= "Tag an IP address on a Palo Alto Networks Next generation Firewall") parser.add_argument("-v", "--verbose", action="count", help="Verbose (-vv for extra verbose)") parser.add_argument("-q", "--quiet", action="store_true", help="No output") parser.add_argument( "-r", "--register", help= "Tags to register to an IP, for multiple tags use commas eg. linux,apache,server", ) parser.add_argument( "-u", "--unregister", help= "Tags to remove from an an IP, for multiple tags use commas eg. linux,apache,server", ) parser.add_argument( "-s", "--vsys", help= "Specify the vsys target in the form vsysN where N is the vsys number: vsys2, vsys4, etc.", ) parser.add_argument("-l", "--list", action="store_true", help="List all tags for an IP") parser.add_argument("-c", "--clear", action="store_true", help="Clear all tags for all IP") # Palo Alto Networks related arguments fw_group = parser.add_argument_group("Palo Alto Networks Device") fw_group.add_argument("hostname", help="Hostname of Firewall") fw_group.add_argument("username", help="Username for Firewall") fw_group.add_argument("password", help="Password for Firewall") fw_group.add_argument("ip", help="The IP address to tag/untag/list") args = parser.parse_args() ### Set up logger # Logging Levels # WARNING is 30 # INFO is 20 # DEBUG is 10 if args.verbose is None: args.verbose = 0 if not args.quiet: logging_level = 20 - (args.verbose * 10) if logging_level <= logging.DEBUG: logging_format = "%(levelname)s:%(name)s:%(message)s" else: logging_format = "%(message)s" logging.basicConfig(format=logging_format, level=logging_level) # Connect to the device and determine its type (Firewall or Panorama). device = PanDevice.create_from_device( args.hostname, args.username, args.password, ) # Panorama does not have a userid API, so exit. # You can use the userid API on a firewall with the Panorama 'target' # parameter by creating a Panorama object first, then create a # Firewall object with the 'panorama' and 'serial' variables populated. if issubclass(type(device), Panorama): logging.error( "Connected to a Panorama, but user-id API is not possible on Panorama. Exiting." ) sys.exit(1) if args.vsys is not None: device.vsys = args.vsys if args.clear: device.userid.clear_registered_ip() if args.list: all_tags_by_ip = device.userid.get_registered_ip() try: # Print the tags for the requested IP logging.info(all_tags_by_ip[args.ip]) except KeyError: # There were no tags for that IP logging.info("No tags for IP: %s" % args.ip) if args.unregister: device.userid.unregister(args.ip, args.unregister.split(",")) if args.register: device.userid.register(args.ip, args.register.split(","))
def get_pandevice_parent(self, module, timeout=0): """Builds the pandevice object tree, returning the parent object. If pandevice is not installed, then module.fail_json() will be invoked. Arguments: * module(AnsibleModule): the ansible module. * timeout(int): Number of seconds to retry opening the connection to PAN-OS. Returns: * The parent pandevice object based on the spec given to get_connection(). """ # Sanity check. if not HAS_PANDEVICE: module.fail_json(msg='Missing required library "pandevice".') pdv = tuple(int(x) for x in panos.__version__.split(".")) # Inform people that they should upgrade to pan-os-python instead of pandevice. if pdv < (1, 0, 0): lum = [ 'Python library "pandevice" is now "pan-os-python" and is now 1.0!', 'Please "pip install pan-os-python" at your earliest convenience.', ] module.deprecate(" ".join(lum), version="3.0.0", collection_name="paloaltonetworks.panos") # Verify pandevice minimum version. if self.min_pandevice_version is not None: if pdv < self.min_pandevice_version: module.fail_json(msg=_MIN_VERSION_ERROR.format( "panos", panos.__version__, _vstr(self.min_pandevice_version))) pan_device_auth, serial_number = None, None if module.params["provider"] and module.params["provider"][ "ip_address"]: pan_device_auth = ( module.params["provider"]["ip_address"], module.params["provider"]["username"], module.params["provider"]["password"], module.params["provider"]["api_key"], module.params["provider"]["port"], ) serial_number = module.params["provider"]["serial_number"] elif module.params.get("ip_address", None) is not None: pan_device_auth = ( module.params["ip_address"], module.params["username"], module.params["password"], module.params["api_key"], module.params["port"], ) msg = 'Classic provider params are deprecated; use "provider" instead' module.deprecate(msg, version="3.0.0", collection_name="paloaltonetworks.panos") else: module.fail_json(msg="Provider params are required.") # Create the connection object. if not isinstance(timeout, int): raise ValueError("Timeout must be an int") elif timeout < 0: raise ValueError("Timeout must greater than or equal to 0") end_time = time.time() + timeout while True: try: self.device = PanDevice.create_from_device(*pan_device_auth) except PanDeviceError as e: if timeout == 0: module.fail_json(msg="Failed connection: {0}".format(e)) elif time.time() >= end_time: module.fail_json(msg="Connection timeout: {0}".format(e)) else: break # Verify PAN-OS minimum version. if self.min_panos_version is not None: if self.device._version_info < self.min_panos_version: module.fail_json(msg=_MIN_VERSION_ERROR.format( "PAN-OS", _vstr(self.device._version_info), _vstr(self.min_panos_version), )) # Optional: Firewall via Panorama connectivity specified. if hasattr(self.device, "refresh_devices") and serial_number: fw = Firewall(serial=serial_number) self.device.add(fw) self.device = fw parent = self.device no_shared = 'Scope "shared" is not allowed' not_found = '{0} "{1}" is not present.' pano_mia_param = 'Param "{0}" is required for Panorama but not specified.' ts_error = "Specify either the template or the template stack{0}." if hasattr(self.device, "refresh_devices"): # Panorama connection. templated = False # Error if Panorama is not supported. if self.panorama_error is not None: module.fail_json(msg=self.panorama_error) # Spec: template stack. tmpl_required = False added_template = False if self.template_stack is not None: name = module.params[self.template_stack] if name is not None: templated = True stacks = TemplateStack.refreshall(parent, name_only=True) for ts in stacks: if ts.name == name: parent = ts added_template = True break else: module.fail_json(msg=not_found.format( "Template stack", name, )) elif self.template is not None: tmpl_required = True elif not self.template_is_optional: module.fail_json( msg=pano_mia_param.format(self.template_stack)) # Spec: template. if self.template is not None: name = module.params[self.template] if name is not None: templated = True if added_template: module.fail_json(msg=ts_error.format(", not both")) templates = Template.refreshall(parent, name_only=True) for t in templates: if t.name == name: parent = t break else: module.fail_json(msg=not_found.format( "Template", name, )) elif self.template_is_optional: pass elif tmpl_required: module.fail_json(msg=ts_error.format("")) elif not added_template: module.fail_json(msg=pano_mia_param.format(self.template)) # Spec: vsys_dg or device_group. dg_name = self.vsys_dg or self.device_group if dg_name is not None: name = module.params[dg_name] if name not in (None, "shared"): groups = DeviceGroup.refreshall(parent, name_only=True) for dg in groups: if dg.name == name: parent = dg break else: module.fail_json(msg=not_found.format( "Device group", name, )) # Spec: vsys importable. vsys_name = self.vsys_importable or self.vsys or self.vsys_shared if dg_name is None and templated and vsys_name is not None: name = module.params[vsys_name] if name not in (None, "shared"): vo = Vsys(name) parent.add(vo) parent = vo # Spec: rulebase. if self.rulebase is not None: if module.params[self.rulebase] in (None, "pre-rulebase"): rb = PreRulebase() parent.add(rb) parent = rb elif module.params[self.rulebase] == "rulebase": rb = Rulebase() parent.add(rb) parent = rb elif module.params[self.rulebase] == "post-rulebase": rb = PostRulebase() parent.add(rb) parent = rb else: module.fail_json(msg=not_found.format( "Rulebase", module.params[self.rulebase])) else: # Firewall connection. # Error if firewalls are not supported. if self.firewall_error is not None: module.fail_json(msg=self.firewall_error) # Spec: vsys or vsys_dg or vsys_importable. vsys_name = (self.vsys_dg or self.vsys or self.vsys_importable or self.vsys_shared) if vsys_name is not None: parent.vsys = module.params[vsys_name] if parent.vsys == "shared" and self.error_on_firewall_shared: module.fail_json(msg=no_shared) # Spec: rulebase. if self.rulebase is not None: rb = Rulebase() parent.add(rb) parent = rb # If the module has the commit option set, show a deprecation warning. if module.params.get("commit"): module.deprecate( "Please use the commit modules instead of the commit option", version="3.0.0", collection_name="paloaltonetworks.panos", ) # Done. return parent
def main(): # Get command line arguments parser = argparse.ArgumentParser( description="Update User-ID by adding or removing a user-to-ip mapping" ) parser.add_argument( "-v", "--verbose", action="count", help="Verbose (-vv for extra verbose)" ) parser.add_argument("-q", "--quiet", action="store_true", help="No output") # Palo Alto Networks related arguments fw_group = parser.add_argument_group("Palo Alto Networks Device") fw_group.add_argument("hostname", help="Hostname of Firewall") fw_group.add_argument("username", help="Username for Firewall") fw_group.add_argument("password", help="Password for Firewall") fw_group.add_argument( "action", help="The action of the user. Must be 'login' or 'logout'." ) fw_group.add_argument("user", help="The username of the user") fw_group.add_argument("ip", help="The IP address of the user") args = parser.parse_args() ### Set up logger # Logging Levels # WARNING is 30 # INFO is 20 # DEBUG is 10 if args.verbose is None: args.verbose = 0 if not args.quiet: logging_level = 20 - (args.verbose * 10) if logging_level <= logging.DEBUG: logging_format = "%(levelname)s:%(name)s:%(message)s" else: logging_format = "%(message)s" logging.basicConfig(format=logging_format, level=logging_level) # Connect to the device and determine its type (Firewall or Panorama). device = PanDevice.create_from_device(args.hostname, args.username, args.password,) logging.debug("Detecting type of device") # Panorama does not have a userid API, so exit. # You can use the userid API on a firewall with the Panorama 'target' # parameter by creating a Panorama object first, then create a # Firewall object with the 'panorama' and 'serial' variables populated. if issubclass(type(device), Panorama): logging.error( "Connected to a Panorama, but user-id API is not possible on Panorama. Exiting." ) sys.exit(1) if args.action == "login": logging.debug("Login user %s at IP %s" % (args.user, args.ip)) device.userid.login(args.user, args.ip) elif args.action == "logout": logging.debug("Logout user %s at IP %s" % (args.user, args.ip)) device.userid.logout(args.user, args.ip) else: raise ValueError( "Unknown action: %s. Must be 'login' or 'logout'." % args.action ) logging.debug("Done")
def main(): argument_spec = dict( ip_address=dict(required=True), password=dict(no_log=True), username=dict(default="admin"), api_key=dict(no_log=True), operation=dict(required=True, choices=["add", "update", "delete", "find"]), addressobject=dict(default=None), addressgroup=dict(default=None), serviceobject=dict(default=None), servicegroup=dict(default=None), address=dict(default=None), address_type=dict(default="ip-netmask", choices=["ip-netmask", "ip-range", "fqdn"]), static_value=dict(type="list", elements="str", default=None), dynamic_value=dict(default=None), protocol=dict(default=None, choices=["tcp", "udp"]), source_port=dict(default=None), destination_port=dict(default=None), services=dict(type="list", elements="str", default=None), description=dict(default=None), tag_name=dict(default=None), color=dict( default=None, choices=[ "red", "green", "blue", "yellow", "copper", "orange", "purple", "gray", "light green", "cyan", "light gray", "blue gray", "lime", "black", "gold", "brown", ], ), vsys=dict(default="vsys1"), devicegroup=dict(default=None), commit=dict(type="bool", default=False), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=False, required_one_of=[["api_key", "password"]], mutually_exclusive=[[ "addressobject", "addressgroup", "serviceobject", "servicegroup", "tag_name", ]], ) if not HAS_LIB: module.fail_json(msg="Missing required libraries.") ip_address = module.params["ip_address"] password = module.params["password"] username = module.params["username"] api_key = module.params["api_key"] operation = module.params["operation"] addressobject = module.params["addressobject"] addressgroup = module.params["addressgroup"] serviceobject = module.params["serviceobject"] servicegroup = module.params["servicegroup"] address = module.params["address"] address_type = module.params["address_type"] static_value = module.params["static_value"] dynamic_value = module.params["dynamic_value"] protocol = module.params["protocol"] source_port = module.params["source_port"] destination_port = module.params["destination_port"] services = module.params["services"] description = module.params["description"] tag_name = module.params["tag_name"] color = module.params["color"] vsys = module.params["vsys"] devicegroup = module.params["devicegroup"] commit = module.params["commit"] # Create the device with the appropriate pandevice type device = PanDevice.create_from_device(ip_address, username, password, api_key=api_key) # If Panorama, validate the devicegroup dev_group = None if hasattr(device, "refresh_devices"): # Panorama: set the device group. if devicegroup == "shared": # Device group of None is "shared" scope for Panorama. devicegroup = None if devicegroup is not None: 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) else: # Firewall: set the targetted vsys. device.vsys = vsys # What type of object are we talking about? if addressobject: obj_name = addressobject obj_type = objects.AddressObject elif addressgroup: obj_name = addressgroup obj_type = objects.AddressGroup elif serviceobject: obj_name = serviceobject obj_type = objects.ServiceObject elif servicegroup: obj_name = servicegroup obj_type = objects.ServiceGroup elif tag_name: obj_name = tag_name obj_type = objects.Tag else: module.fail_json(msg="No object type defined!") # Which operation shall we perform on the object? msg = None if operation == "find": # Search for the object match = find_object(device, dev_group, obj_name, obj_type) # If found, format and return the result if match: match_dict = xmltodict.parse(match.element_str()) module.exit_json(stdout_lines=json.dumps(match_dict, indent=2), msg="Object matched") else: module.fail_json( msg="Object '%s' not found. Is the name correct?" % obj_name) elif operation == "delete": # Search for the object match = find_object(device, dev_group, obj_name, obj_type) # If found, delete it if match: try: match.delete() except PanXapiError as e: module.fail_json(msg=e.message) msg = "Object '{0}' successfully deleted".format(obj_name) else: module.fail_json( msg="Object '%s' not found. Is the name correct?" % obj_name) elif operation == "add": # Search for the object. Fail if found. match = find_object(device, dev_group, obj_name, obj_type) if match: module.fail_json( msg= "Object '%s' already exists. Use operation: 'update' to change it." % obj_name) else: try: new_object = create_object( addressobject=addressobject, addressgroup=addressgroup, serviceobject=serviceobject, servicegroup=servicegroup, address=address, address_type=address_type, static_value=static_value, dynamic_value=dynamic_value, protocol=protocol, source_port=source_port, destination_port=destination_port, services=services, description=description, tag_name=tag_name, color=color, ) changed = add_object(device, dev_group, new_object) except PanXapiError as e: module.fail_json(msg=e.message) msg = "Object '{0}' successfully added".format(obj_name) elif operation == "update": # Search for the object. Update if found. match = find_object(device, dev_group, obj_name, obj_type) if match: try: new_object = create_object( addressobject=addressobject, addressgroup=addressgroup, serviceobject=serviceobject, servicegroup=servicegroup, address=address, address_type=address_type, static_value=static_value, dynamic_value=dynamic_value, protocol=protocol, source_port=source_port, destination_port=destination_port, services=services, description=description, tag_name=tag_name, color=color, ) changed = add_object(device, dev_group, new_object) except PanXapiError as e: module.fail_json(msg=e.message) msg = "Object '{0}' successfully updated.".format(obj_name) else: module.fail_json( msg= "Object '%s' does not exist. Use operation: 'add' to add it." % obj_name) # Optional: commit the change. if commit: try: device.commit(sync=True) except PanDeviceError as e: module.fail_json(msg="Failed to commit: {0}".format(e)) # Done. module.exit_json(changed=True, msg=msg)
def main(): argument_spec = dict( ip_address=dict(required=True), password=dict(no_log=True), username=dict(default='admin'), api_key=dict(no_log=True), operation=dict(required=True, choices=['add', 'update', 'delete', 'find']), addressobject=dict(default=None), addressgroup=dict(default=None), serviceobject=dict(default=None), servicegroup=dict(default=None), address=dict(default=None), address_type=dict(default='ip-netmask', choices=['ip-netmask', 'ip-range', 'fqdn']), static_value=dict(type='list', elements='str', default=None), dynamic_value=dict(default=None), protocol=dict(default=None, choices=['tcp', 'udp']), source_port=dict(default=None), destination_port=dict(default=None), services=dict(type='list', elements='str', default=None), description=dict(default=None), tag_name=dict(default=None), color=dict(default=None, choices=[ 'red', 'green', 'blue', 'yellow', 'copper', 'orange', 'purple', 'gray', 'light green', 'cyan', 'light gray', 'blue gray', 'lime', 'black', 'gold', 'brown' ]), vsys=dict(default='vsys1'), devicegroup=dict(default=None), commit=dict(type='bool', default=False), ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['api_key', 'password']], mutually_exclusive=[[ 'addressobject', 'addressgroup', 'serviceobject', 'servicegroup', 'tag_name' ]]) if not HAS_LIB: module.fail_json(msg='Missing required libraries.') ip_address = module.params["ip_address"] password = module.params["password"] username = module.params['username'] api_key = module.params['api_key'] operation = module.params['operation'] addressobject = module.params['addressobject'] addressgroup = module.params['addressgroup'] serviceobject = module.params['serviceobject'] servicegroup = module.params['servicegroup'] address = module.params['address'] address_type = module.params['address_type'] static_value = module.params['static_value'] dynamic_value = module.params['dynamic_value'] protocol = module.params['protocol'] source_port = module.params['source_port'] destination_port = module.params['destination_port'] services = module.params['services'] description = module.params['description'] tag_name = module.params['tag_name'] color = module.params['color'] vsys = module.params['vsys'] devicegroup = module.params['devicegroup'] commit = module.params['commit'] # Create the device with the appropriate pandevice type device = PanDevice.create_from_device(ip_address, username, password, api_key=api_key) # If Panorama, validate the devicegroup dev_group = None if hasattr(device, 'refresh_devices'): # Panorama: set the device group. if devicegroup == 'shared': # Device group of None is "shared" scope for Panorama. devicegroup = None if devicegroup is not None: 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) else: # Firewall: set the targetted vsys. device.vsys = vsys # What type of object are we talking about? if addressobject: obj_name = addressobject obj_type = objects.AddressObject elif addressgroup: obj_name = addressgroup obj_type = objects.AddressGroup elif serviceobject: obj_name = serviceobject obj_type = objects.ServiceObject elif servicegroup: obj_name = servicegroup obj_type = objects.ServiceGroup elif tag_name: obj_name = tag_name obj_type = objects.Tag else: module.fail_json(msg='No object type defined!') # Which operation shall we perform on the object? msg = None if operation == "find": # Search for the object match = find_object(device, dev_group, obj_name, obj_type) # If found, format and return the result if match: match_dict = xmltodict.parse(match.element_str()) module.exit_json(stdout_lines=json.dumps(match_dict, indent=2), msg='Object matched') else: module.fail_json( msg='Object \'%s\' not found. Is the name correct?' % obj_name) elif operation == "delete": # Search for the object match = find_object(device, dev_group, obj_name, obj_type) # If found, delete it if match: try: match.delete() except PanXapiError as e: module.fail_json(msg=e.message) msg = "Object '{0}' successfully deleted".format(obj_name) else: module.fail_json( msg='Object \'%s\' not found. Is the name correct?' % obj_name) elif operation == "add": # Search for the object. Fail if found. match = find_object(device, dev_group, obj_name, obj_type) if match: module.fail_json( msg= 'Object \'%s\' already exists. Use operation: \'update\' to change it.' % obj_name) else: try: new_object = create_object(addressobject=addressobject, addressgroup=addressgroup, serviceobject=serviceobject, servicegroup=servicegroup, address=address, address_type=address_type, static_value=static_value, dynamic_value=dynamic_value, protocol=protocol, source_port=source_port, destination_port=destination_port, services=services, description=description, tag_name=tag_name, color=color) changed = add_object(device, dev_group, new_object) except PanXapiError as e: module.fail_json(msg=e.message) msg = "Object '{0}' successfully added".format(obj_name) elif operation == "update": # Search for the object. Update if found. match = find_object(device, dev_group, obj_name, obj_type) if match: try: new_object = create_object(addressobject=addressobject, addressgroup=addressgroup, serviceobject=serviceobject, servicegroup=servicegroup, address=address, address_type=address_type, static_value=static_value, dynamic_value=dynamic_value, protocol=protocol, source_port=source_port, destination_port=destination_port, services=services, description=description, tag_name=tag_name, color=color) changed = add_object(device, dev_group, new_object) except PanXapiError as e: module.fail_json(msg=e.message) msg = "Object '{0}' successfully updated.".format(obj_name) else: module.fail_json( msg= 'Object \'%s\' does not exist. Use operation: \'add\' to add it.' % obj_name) # Optional: commit the change. if commit: try: device.commit(sync=True) except PanDeviceError as e: module.fail_json(msg='Failed to commit: {0}'.format(e)) # Done. module.exit_json(changed=True, msg=msg)