def get_pano_dg(): global pano_dg, pan_device all_dgs = pan_device.add(DeviceGroup()).refreshall(pan_device, name_only=True) while True: try: print("\n\nHere's a list of device groups found in Panorama...\n") for index, dg in enumerate(all_dgs): print(f'{index + 1}) {dg.name}') dg_choice = int( input( '\n\nChoose a number for the device-group...\n\nAnswer: ')) pano_dg = all_dgs[dg_choice - 1] except: print("\n\nThat's not a number in the list, try again...\n") time.sleep(.75) continue get_dg_hierarchy(all_dgs) pano_dg.refresh(pan_device) pan_device = pano_dg break
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".') # Verify pandevice minimum version. if self.min_pandevice_version is not None: pdv = tuple(int(x) for x in pandevice.__version__.split('.')) if pdv < self.min_pandevice_version: module.fail_json(msg=_MIN_VERSION_ERROR.format( 'pandevice', pandevice.__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, '2.12') 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 else: 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 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, )) elif self.error_on_shared: module.fail_json(msg=no_shared) # 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_shared: module.fail_json(msg=no_shared) # Spec: rulebase. if self.rulebase is not None: rb = Rulebase() parent.add(rb) parent = rb # Done. return parent
def get_pandevice_parent(self, module): """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. 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".') d, host_arg = None, None if module.params['provider'] and module.params['provider']['host']: d = module.params['provider'] host_arg = 'host' elif module.params['ip_address'] is not None: d = module.params host_arg = 'ip_address' else: module.fail_json(msg='New or classic provider params are required.') # Create the connection object. try: self.device = PanDevice.create_from_device( d[host_arg], d['username'], d['password'], d['api_key']) except PanDeviceError as e: module.fail_json(msg='Failed connection: {0}'.format(e)) parent = self.device not_found = '{0} "{1}" is not present.' if hasattr(self.device, 'refresh_devices'): # Panorama connection. # Error if Panorama is not supported. if self.panorama_error is not None: module.fail_json(msg=self.panorama_error) # Spec: template stack. if self.template_stack is not None: name = module.params[self.template_stack] stacks = TemplateStack.refreshall(parent) for ts in stacks: if ts.name == name: parent = ts break else: module.fail_json(msg=not_found.format( 'Template stack', name, )) # Spec: template. if self.template is not None: name = module.params[self.template] templates = Template.refreshall(parent) for t in templates: if t.name == name: parent = t break else: module.fail_json(msg=not_found.format( 'Template', name, )) # Spec: vsys importable. if self.vsys_importable is not None: name = module.params[self.vsys_importable] if name is not None: vo = Vsys(name) parent.add(vo) parent = vo # 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) for dg in groups: if dg.name == name: parent = dg break else: module.fail_json(msg=not_found.format( 'Device group', name, )) # 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] == '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 if vsys_name is not None: self.con.vsys = module.params[vsys_name] # Spec: rulebase. if self.rulebase is not None: rb = Rulebase() parent.add(rb) parent = rb # Done. return parent
def main(): parser = argparse.ArgumentParser() parser.add_argument('--panorama', help='hostname or ip of panorama', required=True) parser.add_argument( '--master_device', help='hostname or ip of firewall to retrieve group-mappings', required=True) parser.add_argument( '--dg', help= 'device group of the pre-rulebase that contain user-group-based policies', required=True) args = parser.parse_args() try: panorama = Panorama(args.panorama, input('Panorama username: '******'Panorama password: '******'show devices connected' try: res = panorama.op(cmd, xml=True) except PanDeviceError as e: print(e.message) sys.exit(1) devs_connected = xmltodict.parse( res)['response']['result']['devices']['entry'] firewall = None for dev in devs_connected: if dev['hostname'] == args.master_device or dev[ 'ip-address'] == args.master_device: firewall = Firewall(serial=dev['serial']) break if firewall is not None: try: panorama.add(firewall) except PanDeviceError as e: print(e.message) else: print( 'Master device (firewall) is not managed by Panorama. Attempting direct connection to firewall...' ) try: firewall = Firewall(args.master_device, input('Firewall username: '******'Firewall password: '******'Retrieving user-group-mappings on master device: "{}"...'.format( args.master_device)) cmd = 'show user group list' try: res = firewall.op(cmd, xml=True) except PanDeviceError as e: print(e.message) user_group_data = xmltodict.parse(res)['response']['result'] user_group_list = re.findall(r'cn=.*?dc=com', user_group_data) print('Number of mapped user-groups found: {}\n'.format( len(user_group_list))) print('Currently mapped user-groups: ') for user_group in user_group_list: print('"{}"'.format(user_group)) print('\n') try: DeviceGroup.refreshall(panorama) target_dg = panorama.find(args.dg, DeviceGroup) if target_dg is None: print( 'Device group "{}" not found on Panorama device. Aborting...'. format(args.dg)) sys.exit() prb = PreRulebase() target_dg.add(prb) dg_pre_rules = SecurityRule.refreshall(prb) except PanDeviceError as e: print(e.message) print('Retrieving user-based security policy from device-group: "{}"...'. format(args.dg)) user_based_rules = [] for rule in dg_pre_rules: if not 'any' in rule.source_user: user_based_rules.append(rule) print('Number of user-based security rules found: {}\n'.format( len(user_based_rules))) for rule in user_based_rules: print('Validating user-based security rule: "{}"...'.format(rule.name)) for user in rule.source_user: if not user in user_group_list: print('Invalid user-group: "{}"'.format(user)) print('\n')
def get_pandevice_parent(self, module): """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. 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".') # Verify pandevice minimum version. if self.min_pandevice_version is not None: pdv = tuple(int(x) for x in pandevice.__version__.split('.')) if pdv < self.min_pandevice_version: module.fail_json(msg=_MIN_VERSION_ERROR.format( 'pandevice', pandevice.__version__, _vstr(self.min_pandevice_version))) d, host_arg = None, None if module.params['provider'] and module.params['provider']['host']: d = module.params['provider'] host_arg = 'host' elif module.params['ip_address'] is not None: d = module.params host_arg = 'ip_address' else: module.fail_json( msg='New or classic provider params are required.') # Create the connection object. try: self.device = PanDevice.create_from_device(d[host_arg], d['username'], d['password'], d['api_key'], d['port']) except PanDeviceError as e: module.fail_json(msg='Failed connection: {0}'.format(e)) # 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))) parent = self.device 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. # 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: 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 else: 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: 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 tmpl_required: module.fail_json(msg=ts_error.format('')) else: module.fail_json(msg=pano_mia_param.format(self.template)) # Spec: vsys importable. vsys_name = self.vsys_importable or self.vsys if 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: 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: 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 if vsys_name is not None: self.device.vsys = module.params[vsys_name] # Spec: rulebase. if self.rulebase is not None: rb = Rulebase() parent.add(rb) parent = rb # Done. return parent
def get_devicegroup(device, devicegroup): DeviceGroup.refreshall(device, add=True) d = device.find(devicegroup) return d
def main(): parser = argparse.ArgumentParser() parser.add_argument('--panorama', help='hostname or ip of panorama', required=True) parser.add_argument('--user', help='username for auth to panorama', required=True) parser.add_argument( '--dg', help= 'device group of the pre-rulebase that contain user-group-based policies', required=True) parser.add_argument('--group_mapping', help='legacy to PAN LDAP group mappings csv file', required=True) args = parser.parse_args() try: panorama = Panorama(args.panorama, args.user, getpass()) except PanDeviceError as e: print(e.message) print('Retrieving user-based security policy from device-group: "{}"...'. format(args.dg)) try: DeviceGroup.refreshall(panorama) target_dg = panorama.find(args.dg, DeviceGroup) if target_dg is None: print( 'Device group "{}" not found on Panorama device. Aborting...'. format(args.dg)) sys.exit() prb = PreRulebase() target_dg.add(prb) dg_pre_rules = SecurityRule.refreshall(prb) except PanDeviceError as e: print(e.message) with open(args.group_mapping, newline='') as csvfile: reader = csv.reader(csvfile) group_map_dict = {} for row in reader: group_map_dict[row[0]] = row[1] changed = None for rule in dg_pre_rules: if not 'any' in rule.source_user: print(rule.name) for k, v in group_map_dict.items(): for user in rule.source_user: if user == k: print('{0} -> {1}'.format(user, v)) if not v in rule.source_user: rule.source_user.append(v) rule.source_user.remove(k) changed = True if changed: try: rule.apply() changed = False except PanDeviceError as e: print(e.message)