Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
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),
                         zone=dict(required=True),
                         mode=dict(choices=[
                             'tap', 'virtual-wire', 'layer2', 'layer3',
                             'external'
                         ],
                                   default='layer3'),
                         interface=dict(type='list'),
                         zone_profile=dict(),
                         log_setting=dict(),
                         enable_userid=dict(type='bool', default=False),
                         include_acl=dict(type='list'),
                         exclude_acl=dict(type='list'),
                         vsys=dict(default='vsys1'),
                         template=dict(),
                         state=dict(choices=['present', 'absent'],
                                    default='present'))
    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.')

    # Get the firewall / panorama auth.
    auth = (
        module.params['ip_address'],
        module.params['username'],
        module.params['password'],
        module.params['api_key'],
    )

    # Set the Zone object params
    zone_spec = {
        'name': module.params['zone'],
        'mode': module.params['mode'],
        'interface': module.params['interface'],
        'zone_profile': module.params['zone_profile'],
        'log_setting': module.params['log_setting'],
        'enable_user_identification': module.params['enable_userid'],
        'include_acl': module.params['include_acl'],
        'exclude_acl': module.params['exclude_acl']
    }

    # Get other info
    vsys = module.params['vsys']
    template = module.params['template']
    state = module.params['state']

    # 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)

    # Set the attachment point for the Zone object
    parent = None
    if isinstance(device, Firewall):
        parent = device
    elif isinstance(device, Panorama):
        if template is not None:
            template_list = Template.refreshall(device)
            parent = get_template(template, template_list)
            if parent is None:
                module.fail_json(
                    msg='Template not found: {0}'.format(template))
        else:
            module.fail_json(
                msg=
                'A template parameter is required when device type is Panorama'
            )
    if vsys is not None:
        v = Vsys(vsys)
        parent.add(v)
        parent = v

    # Retrieve the current list of zones
    try:
        zones = Zone.refreshall(parent)
    except PanDeviceError:
        e = get_exception()
        module.fail_json(msg=e.message)

    # Build the zone and attach to the parent
    new_zone = Zone(**zone_spec)
    parent.add(new_zone)

    # Which action shall we take on the Zone object?
    changed = False
    if state == 'present':
        match = find_zone(zones, new_zone)
        if match:
            # Change an existing zone
            if not match.equal(new_zone):
                try:
                    if not module.check_mode:
                        new_zone.create()
                except PanDeviceError as e:
                    module.fail_json(
                        msg='Failed "present" create: {0}'.format(e))
                else:
                    changed = True
        else:
            # Add a new zone
            try:
                if not module.check_mode:
                    new_zone.apply()
            except PanDeviceError as e:
                module.fail_json(msg='Failed "present" apply: {0}'.format(e))
            else:
                changed = True
    elif state == 'absent':
        match = find_zone(zones, new_zone)
        if match:
            # Delete an existing zone
            try:
                if not module.check_mode:
                    new_zone.delete()
            except PanDeviceError as e:
                module.fail_json(msg='Failed "absent" delete: {0}'.format(e))
            else:
                changed = True

    # Done!
    module.exit_json(changed=changed, msg='Done')
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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