def populate_facts(self): # Get session usage XML session_root = self.parent.op('show session meter') # Loop through all VSYS virtual_systems = [] vsys_list = Vsys.refreshall(self.parent, name_only=True) for vsys in vsys_list: for var in ('display_name', 'interface', 'virtual_routers'): vsys.refresh_variable(var) zones = [x.name for x in Zone.refreshall(vsys, name_only=True)] vsys_id = vsys.name[4:] vsys_sessions = session_root.find(".//entry/[vsys='" + vsys_id + "']") vsys_currentsessions = vsys_sessions.find('.//current').text vsys_maxsessions = vsys_sessions.find('.//maximum').text virtual_systems.append({ 'vsys_id': vsys_id, 'vsys_name': vsys.name, 'vsys_description': vsys.display_name, 'vsys_iflist': vsys.interface, 'vsys_vrlist': vsys.virtual_routers, 'vsys_zonelist': zones, 'vsys_maxsessions': vsys_maxsessions, 'vsys_currentsessions': vsys_currentsessions, }) self.facts.update({ 'virtual-systems': virtual_systems })
def test_01_setup(self, dev, state_map): state = state_map.setdefault(dev) state.err = True state.fail_func = pytest.skip state.parent = dev state.tmpl = None state.name = None state.obj = None state.targets = [testlib.random_name() for x in range(2)] if self.FUNC is None: pytest.skip('{0}.FUNC must be defined'.format( self.__class__.__name__)) elif self.CLASS is None: pytest.skip('{0}.CLASS must be defined'.format( self.__class__.__name__)) elif self.PARAM is None: pytest.skip('{0}.PARAM must be defined'.format( self.__class__.__name__)) if isinstance(state.parent, Panorama): tmpl = Template(testlib.random_name()) state.parent.add(tmpl) v = Vsys('vsys2') tmpl.add(v) state.parent = v tmpl.create() state.tmpl = tmpl else: vsys_list = [ x.name for x in Vsys.refreshall(dev, add=False, name_only=True) ] if 'vsys2' not in vsys_list: pytest.skip('Firewall needs vsys2 to exist') cls_args = {} eth_args = {'mode': 'layer3'} if self.CLASS == Vlan: eth_args['mode'] = 'layer2' elif self.CLASS == Zone: cls_args['mode'] = 'layer3' state.name = testlib.get_available_interfaces(state.parent)[0] state.obj = EthernetInterface(state.name, **eth_args) state.parent.add(state.obj) if state.tmpl is None: dev.vsys = 'vsys2' instances = [ self.CLASS(state.targets[x], **cls_args) for x in range(2) ] for x in instances: state.parent.add(x) x.create() state.err = False
def test_01_setup(self, dev, state_map): state = state_map.setdefault(dev) state.err = True state.fail_func = pytest.skip state.parent = dev state.tmpl = None state.name = None state.obj = None state.targets = [testlib.random_name() for x in range(2)] if self.FUNC is None: pytest.skip('{0}.FUNC must be defined'.format( self.__class__.__name__)) elif self.CLASS is None: pytest.skip('{0}.CLASS must be defined'.format( self.__class__.__name__)) elif self.PARAM is None: pytest.skip('{0}.PARAM must be defined'.format( self.__class__.__name__)) if isinstance(state.parent, Panorama): tmpl = Template(testlib.random_name()) state.parent.add(tmpl) v = Vsys('vsys2') tmpl.add(v) state.parent = v tmpl.create() state.tmpl = tmpl else: vsys_list = [x.name for x in Vsys.refreshall(dev, add=False, name_only=True)] if 'vsys2' not in vsys_list: pytest.skip('Firewall needs vsys2 to exist') cls_args = {} eth_args = {'mode': 'layer3'} if self.CLASS == Vlan: eth_args['mode'] = 'layer2' elif self.CLASS == Zone: cls_args['mode'] = 'layer3' state.name = testlib.get_available_interfaces(state.parent)[0] state.obj = EthernetInterface(state.name, **eth_args) state.parent.add(state.obj) if state.tmpl is None: dev.vsys = 'vsys2' instances = [self.CLASS(state.targets[x], **cls_args) for x in range(2)] for x in instances: state.parent.add(x) x.create() state.err = False
def sanity(self, dev, state_map, fw_test=False): state = state_map.setdefault(dev) if state.err: state.fail_func('prereq failed') if fw_test: if not isinstance(dev, Firewall): pytest.skip('Skipping firewall-only test') dev.removeall() dev.add(state.obj) vsys_list = Vsys.refreshall(dev, name_only=True) for v in vsys_list: v.refresh_variable(self.VSYS_PARAM) return state
def assert_imported_into(self, vsys, state): found = False vsys_list = Vsys.refreshall(state.parent, add=False, name_only=True) for v in vsys_list: v.refresh_variable(self.VSYS_PARAM) if getattr(v, self.VSYS_PARAM) is None: setattr(v, self.VSYS_PARAM, []) if vsys == v.name: found = True assert state.name in getattr(v, self.VSYS_PARAM) else: assert state.name not in getattr(v, self.VSYS_PARAM) if vsys is not None: assert found
def test_01_setup(self, dev, state_map): state = state_map.setdefault(dev) state.err = True state.fail_func = pytest.skip state.parent = dev state.name = None state.delete_parent = False state.obj = None if self.CLASS is None: pytest.skip('{0}.CLASS must be defined'.format( self.__class__.__name__)) elif self.VSYS_PARAM is None: pytest.skip('{0}.VSYS_PARAM must be defined'.format( self.__class__.__name__)) if isinstance(state.parent, Panorama): tmpl = Template(testlib.random_name()) state.parent.add(tmpl) state.parent = tmpl state.parent.add(Vsys('vsys1')) state.parent.add(Vsys('vsys2')) state.parent.add(Vsys('vsys3')) state.parent.create() state.delete_parent = True else: vsys_list = [ x.name for x in Vsys.refreshall(dev, add=False, name_only=True) ] if not all('vsys{0}'.format(x) in vsys_list for x in range(1, 4)): pytest.skip('Firewall needs vsys1 - vsys3 to exist') args = {} if self.CLASS == EthernetInterface: state.name = testlib.get_available_interfaces(state.parent)[0] args = {'mode': 'layer3'} else: state.name = testlib.random_name() state.obj = self.CLASS(state.name, **args) state.parent.add(state.obj) state.err = False
def test_01_setup(self, dev, state_map): state = state_map.setdefault(dev) state.err = True state.fail_func = pytest.skip state.parent = dev state.name = None state.delete_parent = False state.obj = None if self.CLASS is None: pytest.skip('{0}.CLASS must be defined'.format( self.__class__.__name__)) elif self.VSYS_PARAM is None: pytest.skip('{0}.VSYS_PARAM must be defined'.format( self.__class__.__name__)) if isinstance(state.parent, Panorama): tmpl = Template(testlib.random_name()) state.parent.add(tmpl) state.parent = tmpl state.parent.add(Vsys('vsys1')) state.parent.add(Vsys('vsys2')) state.parent.add(Vsys('vsys3')) state.parent.create() state.delete_parent = True else: vsys_list = [x.name for x in Vsys.refreshall(dev, add=False, name_only=True)] if not all('vsys{0}'.format(x) in vsys_list for x in range(1, 4)): pytest.skip('Firewall needs vsys1 - vsys3 to exist') args = {} if self.CLASS == EthernetInterface: state.name = testlib.get_available_interfaces(state.parent)[0] args = {'mode': 'layer3'} else: state.name = testlib.random_name() state.obj = self.CLASS(state.name, **args) state.parent.add(state.obj) state.err = False
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(default='add', choices=['add', 'update', 'delete']), state=dict(choices=['present', 'absent']), if_name=dict(required=True), ip=dict(type='list'), ipv6_enabled=dict(), management_profile=dict(), mtu=dict(), netflow_profile=dict(), comment=dict(), zone_name=dict(required=True), vr_name=dict(default='default'), vsys_dg=dict(default='vsys1'), commit=dict(type='bool', default=True), ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['api_key', 'password']]) if not HAS_LIB: module.fail_json(msg='Missing required libraries.') # Get the firewall / panorama auth. auth = [ module.params[x] for x in ('ip_address', 'username', 'password', 'api_key') ] # Get the object params. spec = { 'name': module.params['if_name'], 'ip': module.params['ip'], 'ipv6_enabled': module.params['ipv6_enabled'], 'management_profile': module.params['management_profile'], 'mtu': module.params['mtu'], 'netflow_profile': module.params['netflow_profile'], 'comment': module.params['comment'], } # Get other info. operation = module.params['operation'] state = module.params['state'] zone_name = module.params['zone_name'] vr_name = module.params['vr_name'] vsys_dg = module.params['vsys_dg'] commit = module.params['commit'] if_name = module.params['if_name'] # Open the connection to the PANOS device. con = PanDevice.create_from_device(*auth) # Set vsys if firewall, device group if panorama. if hasattr(con, 'refresh_devices'): # Panorama # Normally we want to set the device group here, but there are no # interfaces on Panorama. So if we're given a Panorama device, then # error out. ''' groups = panorama.DeviceGroup.refreshall(con, add=False) for parent in groups: if parent.name == vsys_dg: con.add(parent) break else: module.fail_json(msg="'{0}' device group is not present".format(vsys_dg)) ''' module.fail_json(msg="Ethernet interfaces don't exist on Panorama") else: # Firewall # Normally we should set the vsys here, but since interfaces are # vsys importables, we'll use organize_into_vsys() to help find and # cleanup when the interface is imported into an undesired vsys. # con.vsys = vsys_dg pass # Retrieve the current config. try: interfaces = TunnelInterface.refreshall(con, add=False, name_only=True) zones = Zone.refreshall(con) routers = VirtualRouter.refreshall(con) vsys_list = Vsys.refreshall(con) except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) # Build the object based on the user spec. tun = TunnelInterface(**spec) con.add(tun) # Which action should we take on the interface? changed = False if state == 'present': if tun.name in [x.name for x in interfaces]: i = TunnelInterface(tun.name) con.add(i) try: i.refresh() except PanDeviceError as e: module.fail_json(msg='Failed "present" refresh: {0}'.format(e)) if not i.equal(tun, compare_children=False): tun.extend(i.children) try: tun.apply() changed = True except PanDeviceError as e: module.fail_json( msg='Failed "present" apply: {0}'.format(e)) else: try: tun.create() changed = True except PanDeviceError as e: module.fail_json(msg='Failed "present" create: {0}'.format(e)) try: changed |= set_zone(con, tun, zone_name, zones) changed |= set_virtual_router(con, tun, vr_name, routers) except PanDeviceError as e: module.fail_json(msg='Failed zone/vr assignment: {0}'.format(e)) elif state == 'absent': try: changed |= set_zone(con, tun, None, zones) changed |= set_virtual_router(con, tun, None, routers) except PanDeviceError as e: module.fail_json( msg='Failed "absent" zone/vr cleanup: {0}'.format(e)) changed = True if tun.name in [x.name for x in interfaces]: try: tun.delete() changed = True except PanDeviceError as e: module.fail_json(msg='Failed "absent" delete: {0}'.format(e)) elif operation == 'delete': if tun.name not in [x.name for x in interfaces]: module.fail_json( msg='Interface {0} does not exist, and thus cannot be deleted'. format(tun.name)) try: con.organize_into_vsys() set_zone(con, tun, None, zones) set_virtual_router(con, tun, None, routers) tun.delete() changed = True except (PanDeviceError, ValueError): e = get_exception() module.fail_json(msg=e.message) elif operation == 'add': if tun.name in [x.name for x in interfaces]: module.fail_json( msg='Interface {0} is already present; use operation "update"'. format(tun.name)) con.vsys = vsys_dg # Create the interface. try: tun.create() set_zone(con, tun, zone_name, zones) set_virtual_router(con, tun, vr_name, routers) changed = True except (PanDeviceError, ValueError): e = get_exception() module.fail_json(msg=e.message) elif operation == 'update': if tun.name not in [x.name for x in interfaces]: module.fail_json( msg= 'Interface {0} is not present; use operation "add" to create it' .format(tun.name)) # If the interface is in the wrong vsys, remove it from the old vsys. try: con.organize_into_vsys() except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) if tun.vsys != vsys_dg: try: tun.delete_import() except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) # Move the ethernet object to the correct vsys. for vsys in vsys_list: if vsys.name == vsys_dg: vsys.add(tun) break else: module.fail_json(msg='Vsys {0} does not exist'.format(vsys)) # Update the interface. try: tun.apply() set_zone(con, tun, zone_name, zones) set_virtual_router(con, tun, vr_name, routers) changed = True except (PanDeviceError, ValueError): e = get_exception() module.fail_json(msg=e.message) else: module.fail_json(msg="Unsupported operation '{0}'".format(operation)) # Commit if we were asked to do so. if changed and commit: try: con.commit(sync=True) except PanDeviceError: e = get_exception() module.fail_json(msg='Performed {0} but commit failed: {1}'.format( operation, e.message)) # Done! module.exit_json(changed=changed, msg='okey dokey')
def main(): argument_spec = dict( ip_address=dict(required=True), username=dict(default='admin'), password=dict(no_log=True), api_key=dict(no_log=True), rule_name=dict(required=True), source_zone=dict(type='list', default=['any']), source_ip=dict(type='list', default=["any"]), source_user=dict(type='list', default=['any']), hip_profiles=dict(type='list', default=['any']), destination_zone=dict(type='list', default=['any']), destination_ip=dict(type='list', default=["any"]), application=dict(type='list', default=['any']), service=dict(type='list', default=['application-default']), category=dict(type='list', default=['any']), action=dict(default='allow', choices=[ 'allow', 'deny', 'drop', 'reset-client', 'reset-server', 'reset-both' ]), log_setting=dict(), log_start=dict(type='bool', default=False), log_end=dict(type='bool', default=True), description=dict(default=''), rule_type=dict(default='universal', choices=['universal', 'intrazone', 'interzone']), tag_name=dict(type='list'), negate_source=dict(type='bool', default=False), negate_destination=dict(type='bool', default=False), disabled=dict(type='bool', default=False), schedule=dict(), icmp_unreachable=dict(type='bool'), disable_server_response_inspection=dict(type='bool', default=False), group_profile=dict(), antivirus=dict(), spyware=dict(), vulnerability=dict(), url_filtering=dict(), file_blocking=dict(), wildfire_analysis=dict(), data_filtering=dict(), target=dict(type='list'), negate_target=dict(type='bool', default=False), location=dict(choices=['top', 'bottom', 'before', 'after']), existing_rule=dict(), devicegroup=dict(), rulebase=dict(default='pre-rulebase', choices=['pre-rulebase', 'post-rulebase']), vsys=dict(default='vsys1'), state=dict(choices=['present', 'absent']), operation=dict(default='add', choices=['add', 'update', 'delete', 'find']), commit=dict(type='bool', default=True)) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True, required_one_of=[['api_key', 'password']]) if not HAS_LIB: module.fail_json(msg='Missing required libraries.') elif not hasattr(SecurityRule, 'move'): module.fail_json(msg='Python library pandevice needs to be updated.') # Get the firewall / panorama auth. auth = ( module.params['ip_address'], module.params['username'], module.params['password'], module.params['api_key'], ) # Set the SecurityRule object params rule_spec = { 'name': module.params['rule_name'], 'fromzone': module.params['source_zone'], 'tozone': module.params['destination_zone'], 'source': module.params['source_ip'], 'source_user': module.params['source_user'], 'hip_profiles': module.params['hip_profiles'], 'destination': module.params['destination_ip'], 'application': module.params['application'], 'service': module.params['service'], 'category': module.params['category'], 'action': module.params['action'], 'log_setting': module.params['log_setting'], 'log_start': module.params['log_start'], 'log_end': module.params['log_end'], 'description': module.params['description'], 'type': module.params['rule_type'], 'tag': module.params['tag_name'], 'negate_source': module.params['negate_source'], 'negate_destination': module.params['negate_destination'], 'disabled': module.params['disabled'], 'schedule': module.params['schedule'], 'icmp_unreachable': module.params['icmp_unreachable'], 'disable_server_response_inspection': module.params['disable_server_response_inspection'], 'group': module.params['group_profile'], 'virus': module.params['antivirus'], 'spyware': module.params['spyware'], 'vulnerability': module.params['vulnerability'], 'url_filtering': module.params['url_filtering'], 'file_blocking': module.params['file_blocking'], 'wildfire_analysis': module.params['wildfire_analysis'], 'data_filtering': module.params['data_filtering'], } # Get other info location = module.params['location'] existing_rule = module.params['existing_rule'] devicegroup = module.params['devicegroup'] rulebase = module.params['rulebase'] vsys = module.params['vsys'] state = module.params['state'] operation = module.params['operation'] commit = module.params['commit'] # Sanity check the location / existing_rule params. if location in ('before', 'after') and not existing_rule: module.fail_json( msg= "'existing_rule' must be specified if location is 'before' or 'after'." ) # Open the connection to the PAN-OS device device = None try: device = PanDevice.create_from_device(*auth) except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) # Add some additional rule params if device is Panorama if isinstance(device, Panorama): rule_spec['target'] = module.params['target'] rule_spec['negate_target'] = module.params['negate_target'] # Set the attachment point for the RuleBase object parent = device if isinstance(parent, Firewall): if vsys is not None: vsys_list = Vsys.refreshall(parent) parent = get_vsys(vsys, vsys_list) if parent is None: module.fail_json(msg='VSYS not found: {0}'.format(vsys)) parent = parent.add(Rulebase()) elif isinstance(parent, Panorama): if devicegroup == 'shared': devicegroup = None if devicegroup is not None: parent = parent.add(Rulebase()) else: parent = get_devicegroup(parent, devicegroup) if parent is None: module.fail_json( msg='Device group not found: {0}'.format(devicegroup)) if rulebase == 'pre-rulebase': parent = parent.add(PreRulebase()) elif rulebase == 'post-rulebase': parent = parent.add(PostRulebase()) # Now that we have the rulebase let's grab its security rules rules = SecurityRule.refreshall(parent) # Create new rule object from the params and add to rulebase new_rule = SecurityRule(**rule_spec) parent.add(new_rule) # Which action shall we take on the rule object? changed = False if state == 'present': match = find_rule(rules, new_rule) if match: # Change an existing rule if not match.equal(new_rule): try: if not module.check_mode: new_rule.apply() except PanDeviceError as e: module.fail_json( msg='Failed "present" apply: {0}'.format(e)) else: changed = True else: # Add a new rule try: if not module.check_mode: new_rule.create() except PanDeviceError as e: module.fail_json(msg='Failed "present" apply: {0}'.format(e)) else: changed = True # Move the rule if location is defined if location: try: if not module.check_mode: new_rule.move(location, existing_rule) except PanDeviceError as e: if '{0}'.format(e) not in ACCEPTABLE_MOVE_ERRORS: module.fail_json(msg='Failed move: {0}'.format(e)) else: changed = True elif state == 'absent': match = find_rule(rules, new_rule) if match: # Delete an existing rule try: if not module.check_mode: new_rule.delete() except PanDeviceError as e: module.fail_json(msg='Failed "absent" delete: {0}'.format(e)) else: changed = True elif operation == "find": # Search for the rule match = find_rule(rules, new_rule) # If found, format and return the result if match: module.exit_json(stdout_lines=match.about(), msg='Rule matched') else: module.fail_json( msg='Rule \'%s\' not found. Is the name correct?' % new_rule.name) elif operation == "delete": # Search for the object match = find_rule(rules, new_rule) if match is None: module.fail_json( msg='Rule \'%s\' not found. Is the name correct?' % new_rule.name) try: if not module.check_mode: new_rule.delete() except PanDeviceError as e: module.fail_json(msg='Failed "delete" delete: {0}'.format(e)) else: changed = True elif operation == "add": # Search for the rule. Fail if found. match = find_rule(rules, new_rule) if match: module.fail_json( msg= 'Rule \'%s\' already exists. Use operation: \'update\' to change it.' % new_rule.name) try: if not module.check_mode: new_rule.create() except PanDeviceError as e: module.fail_json(msg='Failed "add" create: {0}'.format(e)) else: changed = True if location: try: if not module.check_mode: new_rule.move(location, existing_rule) except PanDeviceError as e: if '{0}'.format(e) not in ACCEPTABLE_MOVE_ERRORS: module.fail_json(msg='Failed move: {0}'.format(e)) elif operation == 'update': # Search for the rule. Update if found. match = find_rule(rulebase, new_rule.name) if not match: module.fail_json( msg= 'Rule \'%s\' does not exist. Use operation: \'add\' to add it.' % new_rule.name) try: if not module.check_mode: new_rule.apply() except PanDeviceError as e: module.fail_json(msg='Failed "update" apply: {0}'.format(e)) else: changed = True if location: try: if not module.check_mode: new_rule.move(location, existing_rule) except PanDeviceError as e: if '{0}'.format(e) not in ACCEPTABLE_MOVE_ERRORS: module.fail_json(msg='Failed move: {0}'.format(e)) # Optional commit. # FIXME: Commits should be done using the separate commit module if changed and commit: try: device.commit(sync=True) except PanDeviceError as e: module.fail_json(msg='Failed commit: {0}'.format(e)) module.exit_json(changed=changed, msg='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(default='add', choices=['add', 'update', 'delete']), state=dict(choices=['present', 'absent']), if_name=dict(required=True), mode=dict(default='layer3', choices=[ 'layer3', 'layer2', 'virtual-wire', 'tap', 'ha', 'decrypt-mirror', 'aggregate-group' ]), ip=dict(type='list'), ipv6_enabled=dict(), management_profile=dict(), mtu=dict(), adjust_tcp_mss=dict(), netflow_profile=dict(), lldp_enabled=dict(), lldp_profile=dict(), netflow_profile_l2=dict(), link_speed=dict(), link_duplex=dict(), link_state=dict(), aggregate_group=dict(), comment=dict(), ipv4_mss_adjust=dict(), ipv6_mss_adjust=dict(), enable_dhcp=dict(type='bool', default=True), create_default_route=dict(type='bool', default=False), create_dhcp_default_route=dict(type='bool', default=False), dhcp_default_route_metric=dict(), dhcp_default_route=dict(type='str', default="no"), zone_name=dict(required=True), vr_name=dict(default='default'), vsys_dg=dict(default='vsys1'), commit=dict(type='bool', default=True), ) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, required_one_of=[['api_key', 'password']]) if not HAS_LIB: module.fail_json(msg='Missing required libraries.') # Get the firewall / panorama auth. auth = [ module.params[x] for x in ('ip_address', 'username', 'password', 'api_key') ] # Get the object params. spec = { 'name': module.params['if_name'], 'mode': module.params['mode'], 'ip': module.params['ip'], 'ipv6_enabled': module.params['ipv6_enabled'], 'management_profile': module.params['management_profile'], 'mtu': module.params['mtu'], 'adjust_tcp_mss': module.params['adjust_tcp_mss'], 'netflow_profile': module.params['netflow_profile'], 'lldp_enabled': module.params['lldp_enabled'], 'lldp_profile': module.params['lldp_profile'], 'netflow_profile_l2': module.params['netflow_profile_l2'], 'link_speed': module.params['link_speed'], 'link_duplex': module.params['link_duplex'], 'link_state': module.params['link_state'], 'aggregate_group': module.params['aggregate_group'], 'comment': module.params['comment'], 'ipv4_mss_adjust': module.params['ipv4_mss_adjust'], 'ipv6_mss_adjust': module.params['ipv6_mss_adjust'], 'enable_dhcp': module.params['enable_dhcp'] or None, 'create_dhcp_default_route': module.params['create_default_route'] or None, 'dhcp_default_route_metric': module.params['dhcp_default_route_metric'], } # Get other info. enable_dhcp = module.params['enable_dhcp'] operation = module.params['operation'] state = module.params['state'] zone_name = module.params['zone_name'] vr_name = module.params['vr_name'] vsys_dg = module.params['vsys_dg'] commit = module.params['commit'] dhcp_default_route = module.params['dhcp_default_route'] management_profile = module.params['management_profile'] if_name = module.params['if_name'] dhcpe = ( '<entry name="%s"><layer3><dhcp-client><enable>yes</enable><create-default-route>%s</create-default-route>' '</dhcp-client><interface-management-profile>%s</interface-management-profile></layer3></entry>' % (if_name, dhcp_default_route, management_profile)) dhcpx = ( "/config/devices/entry[@name='localhost.localdomain']/network/interface/ethernet/entry[@name='%s']" % (if_name)) # Open the connection to the PANOS device. con = PanDevice.create_from_device(*auth) # Set vsys if firewall, device group if panorama. if hasattr(con, 'refresh_devices'): # Panorama # Normally we want to set the device group here, but there are no # interfaces on Panorama. So if we're given a Panorama device, then # error out. ''' groups = panorama.DeviceGroup.refreshall(con, add=False) for parent in groups: if parent.name == vsys_dg: con.add(parent) break else: module.fail_json(msg="'{0}' device group is not present".format(vsys_dg)) ''' module.fail_json(msg="Ethernet interfaces don't exist on Panorama") else: # Firewall # Normally we should set the vsys here, but since interfaces are # vsys importables, we'll use organize_into_vsys() to help find and # cleanup when the interface is imported into an undesired vsys. # con.vsys = vsys_dg pass # Retrieve the current config. try: interfaces = EthernetInterface.refreshall(con, add=False, name_only=True) zones = Zone.refreshall(con) routers = VirtualRouter.refreshall(con) vsys_list = Vsys.refreshall(con) except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) # Build the object based on the user spec. eth = EthernetInterface(**spec) con.add(eth) # Which action should we take on the interface? changed = False if state == 'present': if eth.name in [x.name for x in interfaces]: i = EthernetInterface(eth.name) con.add(i) try: i.refresh() except PanDeviceError as e: module.fail_json(msg='Failed "present" refresh: {0}'.format(e)) if not i.equal(eth, compare_children=False): eth.extend(i.children) try: eth.apply() changed = True except PanDeviceError as e: module.fail_json( msg='Failed "present" apply: {0}'.format(e)) else: try: eth.create() changed = True except PanDeviceError as e: module.fail_json(msg='Failed "present" create: {0}'.format(e)) try: changed |= set_zone(con, eth, zone_name, zones) changed |= set_virtual_router(con, eth, vr_name, routers) if enable_dhcp is True: con.xapi.edit(xpath=dhcpx, element=dhcpe) except PanDeviceError as e: module.fail_json(msg='Failed zone/vr assignment: {0}'.format(e)) elif state == 'absent': try: changed |= set_zone(con, eth, None, zones) changed |= set_virtual_router(con, eth, None, routers) except PanDeviceError as e: module.fail_json( msg='Failed "absent" zone/vr cleanup: {0}'.format(e)) changed = True if eth.name in [x.name for x in interfaces]: try: eth.delete() changed = True except PanDeviceError as e: module.fail_json(msg='Failed "absent" delete: {0}'.format(e)) elif operation == 'delete': if eth.name not in [x.name for x in interfaces]: module.fail_json( msg='Interface {0} does not exist, and thus cannot be deleted'. format(eth.name)) try: con.organize_into_vsys() set_zone(con, eth, None, zones) set_virtual_router(con, eth, None, routers) eth.delete() changed = True except (PanDeviceError, ValueError): e = get_exception() module.fail_json(msg=e.message) elif operation == 'add': if eth.name in [x.name for x in interfaces]: module.fail_json( msg='Interface {0} is already present; use operation "update"'. format(eth.name)) con.vsys = vsys_dg # Create the interface. try: eth.create() set_zone(con, eth, zone_name, zones) set_virtual_router(con, eth, vr_name, routers) changed = True except (PanDeviceError, ValueError): e = get_exception() module.fail_json(msg=e.message) elif operation == 'update': if eth.name not in [x.name for x in interfaces]: module.fail_json( msg= 'Interface {0} is not present; use operation "add" to create it' .format(eth.name)) # If the interface is in the wrong vsys, remove it from the old vsys. try: con.organize_into_vsys() except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) if eth.vsys != vsys_dg: try: eth.delete_import() except PanDeviceError: e = get_exception() module.fail_json(msg=e.message) # Move the ethernet object to the correct vsys. for vsys in vsys_list: if vsys.name == vsys_dg: vsys.add(eth) break else: module.fail_json(msg='Vsys {0} does not exist'.format(vsys)) # Update the interface. try: eth.apply() set_zone(con, eth, zone_name, zones) set_virtual_router(con, eth, vr_name, routers) changed = True except (PanDeviceError, ValueError): e = get_exception() module.fail_json(msg=e.message) else: module.fail_json(msg="Unsupported operation '{0}'".format(operation)) # Commit if we were asked to do so. if changed and commit: try: con.commit(sync=True, exceptions=True) except PanDeviceError: e = get_exception() module.fail_json(msg='Performed {0} but commit failed: {1}'.format( operation, e.message)) # Done! module.exit_json(changed=changed, msg='okey dokey')