Example #1
0
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,
                                          classify_exceptions=True)

    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 StandardError("Unknown action: %s.  Must be 'login' or 'logout'." % args.action)

    logging.debug("Done")
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('-u', '--unregister', action='store_true', help="Remove the tags (default is register)")
    parser.add_argument('-c', '--clear', action='store_true', help="Clear all tags. ip and tags arguments are ignored")
    # 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 that should be tagged")
    fw_group.add_argument('tags', help="Comma delimited tags.  eg. linux,apache,server")
    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.clear:
        device.userid.clear_all_registered_ip()
        sys.exit(0)

    if args.unregister:
        device.userid.unregister(args.ip, args.tags.split(','))
    else:
        device.userid.register(args.ip, args.tags.split(','))
Example #3
0
def get_dev_type(pan_addr):
    global username, password
    while True:
        try:
            pan_device = PanDevice(pan_addr, username, password)
            if pan_device.refresh_system_info().platform.lower() in [
                    'panorama', 'm-100', 'm-200', 'm-500', 'm-600'
            ]:
                print('\n\n...Auto-detected device type as Panorama...\n')
                return 'pano'
            else:
                print('\n\n...Auto-detected device type as a firewall...\n')
                return 'fw'
        except errors.PanURLError as e:
            if 'invalid credential' in str(e).lower():
                print(
                    '\n\nYour user credentials are invalid, try again...\n\n')
                username, password = get_creds()
            else:
                print('\n\nUnable to connect to device...\n\n')
                exit()
Example #4
0
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)
Example #5
0
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),
        cmd=dict(required=True),
        cmd_is_xml=dict(default=False, type='bool'),
    )
    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.')

    auth = [module.params[x] for x in
            ('ip_address', 'username', 'password', 'api_key')]
    cmd = module.params['cmd']
    cmd_is_xml = module.params['cmd_is_xml']

    # Create the device with the appropriate pandevice type
    try:
        dev = PanDevice.create_from_device(*auth)
    except PanDeviceError as e:
        module.fail_json(msg='Failed to connect: {0}'.format(e))

    changed = False
    xml_output = []
    try:
        xml_output = dev.op(cmd, xml=True, cmd_xml=(not cmd_is_xml))
        changed = True
    except PanDeviceError:
        if cmd_is_xml:
            e = get_exception()
            module.fail_json(
                msg='Failed to run XML command : {0} : {1}'.format(cmd, e))
        tokens = cmd.split()
        tokens[-1] = '"{0}"'.format(tokens[-1])
        cmd2 = ' '.join(tokens)
        try:
            xml_output = dev.op(cmd2, xml=True)
            changed = True
        except PanDeviceError:
            e = get_exception()
            module.fail_json(msg='Failed to run command : {0} : {1}'.format(
                             cmd2, e))

    obj_dict = xmltodict.parse(xml_output)
    json_output = json.dumps(obj_dict)

    module.exit_json(changed=changed, msg="Done",
                     stdout=json_output, stdout_xml=xml_output)
Example #6
0
def cli(hostname, username, password):
    """ PanDevice demo script. """
    try:
        device = PanDevice.create_from_device(hostname,
                                              api_username=username,
                                              api_password=password)

        configure_network(device)
        configure_policy(device)

        device.commit(sync=True)

    except PanDeviceError as e:
        click.echo('PanDeviceError: {}'.format(e))
Example #7
0
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)
Example #8
0
    def get_pandevice(self, firewall):
        if firewall:
            firewall_config = self.config['firewall'].get(firewall)
        else:
            firewall_config = self.config['firewall'].get('default')

        # no need to duplicate config validation because pandevice is verbose enough
        device = None
        try:
            device = PanDevice.create_from_device(
                hostname=firewall_config.get('host'),
                api_username=firewall_config.get('api_username'),
                api_password=firewall_config.get('api_password'),
                api_key=firewall_config.get('api_key'),
                port=firewall_config.get('port'),
            )
        except PanDeviceError as e:
            raise Exception(
                "Failed to connect to firewall {} with pandevice error {}".format(firewall_config,
                                                                                  e)
            )

        return device
Example #9
0
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('-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.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(','))
Example #10
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
Example #11
0
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),
                         state=dict(default='present',
                                    choices=['present', 'absent']),
                         admin_username=dict(default='admin'),
                         authentication_profile=dict(),
                         web_client_cert_only=dict(type='bool'),
                         superuser=dict(type='bool'),
                         superuser_read_only=dict(type='bool'),
                         panorama_admin=dict(type='bool'),
                         device_admin=dict(type='bool'),
                         device_admin_read_only=dict(type='bool'),
                         vsys=dict(type='list'),
                         vsys_read_only=dict(type='list'),
                         ssh_public_key=dict(),
                         role_profile=dict(),
                         admin_password=dict(no_log=True),
                         password_profile=dict(no_log=False),
                         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 PAN-OS auth info.
    auth = [
        module.params[x]
        for x in ['ip_address', 'username', 'password', 'api_key']
    ]

    # Open the connection to the PAN-OS device.
    con = PanDevice.create_from_device(*auth)

    # Get administrator object spec.
    spec_params = [
        'authentication_profile',
        'web_client_cert_only',
        'superuser',
        'superuser_read_only',
        'panorama_admin',
        'device_admin',
        'device_admin_read_only',
        'vsys',
        'vsys_read_only',
        'ssh_public_key',
        'role_profile',
        'password_profile',
    ]
    params = dict((k, module.params[k]) for k in spec_params)
    params['name'] = module.params['admin_username']
    password = module.params['admin_password']

    # Get other params.
    state = module.params['state']
    commit = module.params['commit']

    # Get the current administrators.
    admins = Administrator.refreshall(con, add=False)
    obj = Administrator(**params)
    con.add(obj)

    # Set "password_hash" by requesting a password hash.
    if password is not None:
        try:
            obj.password_hash = con.request_password_hash(password)
        except PanDeviceError as e:
            module.fail_json(msg='Failed to get phash: {0}'.format(e))

    # Perform the requested action.
    changed = False
    if state == 'present':
        for x in admins:
            if obj.name == x.name:
                # If user did not specify a password, keep the current one.
                if obj.password_hash is None and x.password_hash:
                    obj.password_hash = x.password_hash
                # Don't use .equal() here because we don't want pandevice to
                # try and do smart things with the password_hash field.
                if obj.element_str() != x.element_str():
                    try:
                        obj.apply()
                    except PanDeviceError as e:
                        module.fail_json(msg='Failed apply: {0}'.format(e))
                    else:
                        changed = True
                break
        else:
            try:
                obj.create()
            except PanDeviceError as e:
                module.fail_json(msg='Failed create: {0}'.format(e))
            else:
                changed = True
    elif state == 'absent':
        if obj.name in [x.name for x in admins]:
            try:
                obj.delete()
            except PanDeviceError as e:
                module.fail_json(msg='Failed delete: {0}'.format(e))
            else:
                changed = True

    # Commit if appropriate.
    if changed and commit:
        try:
            con.commit(sync=True)
        except PanDeviceError as e:
            module.fail_json(msg='Failed commit: {0}'.format(e))

    # Done.
    module.exit_json(changed=changed, msg='done')
Example #12
0
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 StandardError(
            "Unknown action: %s.  Must be 'login' or 'logout'." % args.action)

    logging.debug("Done")
Example #13
0
def run_module():
    module_args = dict(ip_address=dict(required=True),
                       username=dict(default='admin'),
                       password=dict(no_log=True))

    result = dict(changed=False, packet_loss='', message='')

    module = AnsibleModule(argument_spec=module_args,
                           #support_check_mode=False
                           )

    if not HAS_LIB:
        module.fail_json(
            msg='Missing required libraries: pandevice, netmiko, xmltodict')

    try:
        device = PanDevice.create_from_device(module.params['ip_address'],
                                              module.params['username'],
                                              module.params['password'])
    except PanDeviceError as e:
        module.fail_json(msg=e.message)

    auth = {
        'device_type': 'paloalto_panos',
        'ip': module.params['ip_address'],
        'username': module.params['username'],
        'password': module.params['password']
    }

    try:
        conn = ConnectHandler(**auth)
    except (NetMikoTimeoutException, NetMikoAuthenticationException) as e:
        module.fail_json(msg=e)

    route_table_dict = xmltodict.parse(
        device.op('show routing route', xml=True))['response']['result']
    route_interface_dict = xmltodict.parse(
        device.op('show routing interface', xml=True))['response']['result']

    nexthops = []
    nexthop_interfaces = []

    if 'entry' in route_table_dict:
        for entry in route_table_dict['entry']:
            if ('A' in entry['flags'] and not 'C' in entry['flags']
                    and not 'H' in entry['flags']
                    and entry['nexthop'] != 'discard'
                    and not entry['nexthop'] in nexthops):
                nexthops.append(entry['nexthop'])
                nexthop_interfaces.append(entry['interface'])

    interface_ip_map_dict = {}

    if 'interface' in route_interface_dict:
        for interface in route_interface_dict['interface']:
            if 'address' in interface:
                interface_ip_map_dict[interface['name']] = interface['address']
            else:
                interface_ip_map_dict[interface['name']] = ''

    nexthop_interface_ips = []

    for nexthop_int in nexthop_interfaces:
        for int_name, int_ip in interface_ip_map_dict.items():
            if nexthop_int == int_name:
                nexthop_int = int_ip
                nexthop_interface_ips.append(nexthop_int[:-3])
                break

    packet_loss_dict = {}

    for nexthop, source in list(zip(nexthops, nexthop_interface_ips)):
        if source:
            cmd = 'ping source {} count 2 host {}'.format(source, nexthop)
            raw_text_ping = conn.send_command(
                cmd,
                expect_string=r'(unknown)|(syntax)|(bind)|(\d{1,3})%').strip(
                    'ping\n')
            re_packet_loss = re.search(r'(\d{1,3})%', raw_text_ping)

            if re_packet_loss:
                packet_loss_dict[nexthop] = re_packet_loss.group(0)

    result['packet_loss'] = json.dumps(packet_loss_dict)
    result['message'] = 'Done'
    result['changed'] = True

    conn.disconnect()

    module.exit_json(**result)
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('-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.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(','))
Example #15
0
def main():
    """
   Simple command-line program for shutting down virtual machines on a system.
   """

    args = GetArgs()
    if args.password:
        password = args.password
    else:
        password = getpass.getpass(
            prompt='Enter password for host %s and user %s: ' %
            (args.host, args.user))

    context = ssl._create_unverified_context()

    host = args.host
    user = args.user
    password = args.password
    port = int(args.port)
    vm = args.vmname

    # Set # of CPU cores and memory based on the model.
    if args.model == "50":
        vcpu = 2
        memory = 5632
    elif args.model == "100":
        vcpu = 2
        memory = 6656
    elif args.model == "300":
        vcpu = 4
        memory = 9216
    elif args.model == "500":
        vcpu = 8
        memory = 16384
    elif args.model == "700":
        vcpu = 16
        memory = 57344

    # PAN-OS info:
    pan_hostname = args.pan_host
    pan_username = args.pan_user
    pan_password = args.pan_pass
    auth_code = args.auth_code
    api_key = args.api_key

    service_instance = get_service_instance(host, user, password, port,
                                            context)

    vmobj = get_vm(service_instance, vm)

    if vmobj:
        # Create PAN-OS device am make sure connection can be created. Wait for 5 minutes
        timeout = time.time() + 60 * 5  # 5 min from now
        ready = False
        while time.time() < timeout:
            try:
                device = PanDevice.create_from_device(
                    pan_hostname,
                    api_username=pan_username,
                    api_password=pan_password)
            except PanDeviceError as msg:
                print("PAN-OS is not ready trying again!")
                time.sleep(5)
                pass
            else:
                print("PAN-OS device connection created!")
                ready = True
                break

        if ready:
            # Make sure PAN-OS is ready to accept commands. wait for 5 minutes
            timeout = time.time() + 60 * 5
            if wait_for_panos(device, timeout):
                # De active the current license.
                apply_api_key(device, api_key)
                deactivate_license(device)
                shutdown_vm(vmobj)
                change_vcpu(vmobj, vcpu)
                change_memory(vmobj, memory)
                poweron_vm(vmobj)
                timeout = time.time() + 60 * 5
                # Make sure PAN-OS is ready to accept commands. wait for 5 minutes
                if wait_for_panos(device, timeout):
                    activate_license(device, auth_code)
                    print("Model upgraded to %s successfully!" % args.model)
        else:
            exit(1)
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')
Example #17
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),
        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')
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('-u',
                        '--unregister',
                        action='store_true',
                        help="Remove the tags (default is register)")
    parser.add_argument(
        '-c',
        '--clear',
        action='store_true',
        help="Clear all tags. ip and tags arguments are ignored")
    # 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 that should be tagged")
    fw_group.add_argument(
        'tags', help="Comma delimited tags.  eg. linux,apache,server")
    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.clear:
        device.userid.clear_all_registered_ip()
        sys.exit(0)

    if args.unregister:
        device.userid.unregister(args.ip, args.tags.split(','))
    else:
        device.userid.register(args.ip, args.tags.split(','))
Example #19
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),
        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 delete_from_device(palo: PanDevice, expired: list):
    results = []
    for cert in expired:
        results.append(palo.remove_by_name(cert['@name']))
    return expired
Example #21
0
def main():
    argument_spec = dict(ip_address=dict(required=True),
                         username=dict(default='admin'),
                         password=dict(default='admin', no_log=True),
                         api_key=dict(no_log=True),
                         serialnum=dict(required=True),
                         devicegroup=dict(),
                         templatestack=dict(),
                         state=dict(default='present'))

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True,
                           mutually_exclusive=[['api_key', 'password']])

    if not HAS_LIB:
        module.fail_json(
            msg='pan-python and pandevice are required for this module')

    serialnum = module.params["serialnum"]
    devicegroup = module.params['devicegroup']
    templatestack = module.params['templatestack']
    state = module.params['state']

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

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

    # Ensure we're not connected to a firewall
    if isinstance(device, Firewall):
        module.fail_json(
            msg='This module is only supported on Panorama instances')

    # Set our change flag
    changed = False

    # Add to Panorama if not already connected
    fw = get_firewall(device, serialnum)
    if fw is None and state == 'present' and not module.check_mode:
        fw = Firewall(serial=serialnum)
        device.add(fw)
        fw.create()
        changed = True

    # Process the DeviceGroup
    if devicegroup:
        dg = get_devicegroup(device, devicegroup)
        if dg is None:
            module.fail_json(
                msg="DeviceGroup not found: {0}".format(devicegroup))
        elif dg.find(
                fw.serial, Firewall
        ) is None and state == 'present' and not module.check_mode:
            dg.add(fw)
            fw.create()
            changed = True
        elif dg.find(fw.serial,
                     Firewall) and state == 'absent' and not module.check_mode:
            dg.remove(dg.find(fw.serial))
            dg.apply()
            changed = True

    # Add to the Template Stack
    if templatestack:
        ts = get_templatestack(device, templatestack)
        if ts is None:
            module.fail_json(
                msg="TemplateStack not found: {0}".format(templatestack))
        else:
            listify(ts)
        if fw.serial not in ts.devices and state == 'present' and not module.check_mode:
            ts.devices.append(serialnum)
            ts.create()
            changed = True
        elif fw.serial in ts.devices and state == 'absent' and not module.check_mode:
            ts.devices.remove(fw.serial)
            ts.apply()
            changed = True

    # Remove from Panorama
    if (device.find(fw.serial, Firewall)) and (state == 'absent'):
        device.remove(fw)
        device.apply()
        changed = True

    module.exit_json(changed=changed)
    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 main():
    argument_spec = dict(
        ip_address=dict(required=True),
        username=dict(default='admin'),
        password=dict(no_log=True),
        api_key=dict(no_log=True),
        state=dict(default='present', choices=['present', 'absent']),
        panorama_template=dict(),
        name=dict(required=True),
        ping=dict(type='bool'),
        telnet=dict(type='bool'),
        ssh=dict(type='bool'),
        http=dict(type='bool'),
        http_ocsp=dict(type='bool'),
        https=dict(type='bool'),
        snmp=dict(type='bool'),
        response_pages=dict(type='bool'),
        userid_service=dict(type='bool'),
        userid_syslog_listener_ssl=dict(type='bool'),
        userid_syslog_listener_udp=dict(type='bool'),
        permitted_ip=dict(type='list'),
        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.')

    auth = [
        module.params[x]
        for x in ('ip_address', 'username', 'password', 'api_key')
    ]
    state = module.params['state']
    panorama_template = module.params['panorama_template']
    obj = ManagementProfile(*[
        module.params[x]
        for x in ('name', 'ping', 'telnet', 'ssh', 'http', 'http_ocsp',
                  'https', 'snmp', 'response_pages', 'userid_service',
                  'userid_syslog_listener_ssl', 'userid_syslog_listener_udp',
                  'permitted_ip')
    ])
    commit = module.params['commit']

    # Create the device with the appropriate pandevice type
    dev = PanDevice.create_from_device(*auth)

    # Object tree initialization and parent selection.
    parent = dev
    if hasattr(dev, 'refresh_devices'):
        # This is Panorama.
        if not panorama_template:
            module.fail_json(
                msg="'panorama_template' is required for Panorama")
        ts = Template.refreshall(dev)
        for x in ts:
            if x.name == panorama_template:
                parent = x
                break
        else:
            module.fail_json(
                msg='template "{0}" not found'.format(panorama_template))

    # Check current status.
    try:
        cur_list = ManagementProfile.refreshall(parent)
    except PanDeviceError:
        e = get_exception()
        module.fail_json(msg='Failed refreshall: {0}'.format(e.message))
    parent.add(obj)

    # Determine what function to use based on the desired state.
    func = None
    changed = False
    if state == 'present':
        for x in cur_list:
            if x.name == obj.name:
                if not x.equal(obj, compare_children=False):
                    for child in x.children:
                        obj.add(child)
                    func = 'apply'
                break
        else:
            func = 'create'
    else:
        for x in cur_list:
            if x.name == obj.name:
                func = 'delete'
                break

    # Perform create / apply / delete, if needed.
    if func is not None:
        try:
            getattr(obj, func)()
        except PanDeviceError:
            e = get_exception()
            module.fail_json(msg='Failed {0}: {1}'.format(func, e.message))
        changed = True

        # Perform commit if requested.
        if commit:
            try:
                dev.commit()
            except PanDeviceError:
                e = get_exception()
                module.fail_json(msg='Failed commit: {0}'.format(e.message))

    # Done
    module.exit_json(changed=changed, msg="Done")
Example #24
0
def main():
    argument_spec = dict(
        ip_address=dict(required=True),
        username=dict(default='admin'),
        password=dict(required=True, no_log=True),
        api_key=dict(no_log=True),
        operation=dict(choices=['add', 'update', 'delete', 'find', 'disable']),
        state=dict(default='present', choices=['present', 'absent']),
        rule_name=dict(required=True),
        description=dict(),
        nat_type=dict(default='ipv4', choices=['ipv4', 'nat64', 'nptv6']),
        tag_name=dict(),
        source_zone=dict(type='list'),
        source_ip=dict(type='list', default=['any']),
        destination_zone=dict(),
        destination_ip=dict(type='list', default=['any']),
        service=dict(default='any'),
        to_interface=dict(default='any'),
        snat_type=dict(
            choices=['static-ip', 'dynamic-ip-and-port', 'dynamic-ip']),
        snat_address_type=dict(
            choices=['interface-address', 'translated-address'],
            default='interface-address'),
        snat_static_address=dict(),
        snat_dynamic_address=dict(type='list'),
        snat_interface=dict(),
        snat_interface_address=dict(),
        snat_bidirectional=dict(type='bool', default=False),
        dnat_address=dict(),
        dnat_port=dict(),
        devicegroup=dict(default='shared'),
        rulebase=dict(default='pre-rulebase',
                      choices=['pre-rulebase', 'post-rulebase']),
        vsys=dict(default='vsys1'),
        location=dict(default='bottom',
                      choices=['top', 'bottom', 'before', 'after']),
        existing_rule=dict(),
        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.')
    elif not hasattr(NatRule, 'move'):
        module.fail_json(msg='Python library pandevice needs to be updated.')

    # Get firewall / Panorama auth.
    auth = [
        module.params[x]
        for x in ('ip_address', 'username', 'password', 'api_key')
    ]

    # Get object params.
    rule_name = module.params['rule_name']
    description = module.params['description']
    tag_name = module.params['tag_name']
    source_zone = module.params['source_zone']
    source_ip = module.params['source_ip']
    destination_zone = module.params['destination_zone']
    destination_ip = module.params['destination_ip']
    service = module.params['service']
    to_interface = module.params['to_interface']
    nat_type = module.params['nat_type']
    snat_type = module.params['snat_type']
    snat_address_type = module.params['snat_address_type']
    snat_static_address = module.params['snat_static_address']
    snat_dynamic_address = module.params['snat_dynamic_address']
    snat_interface = module.params['snat_interface']
    snat_interface_address = module.params['snat_interface_address']
    snat_bidirectional = module.params['snat_bidirectional']
    dnat_address = module.params['dnat_address']
    dnat_port = module.params['dnat_port']

    # Get other info.
    operation = module.params['operation']
    state = module.params['state']
    devicegroup = module.params['devicegroup']
    vsys = module.params['vsys']
    commit = module.params['commit']
    location = module.params['location']
    existing_rule = module.params['existing_rule']

    # 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'."
        )

    # Create the device with the appropriate pandevice type
    con = PanDevice.create_from_device(*auth)

    # Set vsys if firewall, device group if Panorama, and set the rulebase.
    parent = con
    if hasattr(con, 'refresh_devices'):
        # Panorama
        if devicegroup not in (None, 'shared'):
            dev_group = get_devicegroup(con, devicegroup)
            if not dev_group:
                module.fail_json(
                    msg=
                    '\'%s\' device group not found in Panorama. Is the name correct?'
                    % devicegroup)
            parent = dev_group
        if module.params['rulebase'] in (None, 'pre-rulebase'):
            rulebase = PreRulebase()
            parent.add(rulebase)
            parent = rulebase
        elif module.params['rulebase'] == 'post-rulebase':
            rulebase = PostRulebase()
            parent.add(rulebase)
            parent = rulebase
    else:
        # Firewall
        parent.vsys = vsys
        rulebase = Rulebase()
        parent.add(rulebase)
        parent = rulebase

    # Get the current NAT rules.
    try:
        rules = NatRule.refreshall(parent)
    except PanDeviceError as e:
        module.fail_json(msg='Failed NAT refreshall: {0}'.format(e))

    # Create the desired rule.
    new_rule = create_nat_rule(rule_name=rule_name,
                               description=description,
                               tag_name=tag_name,
                               source_zone=source_zone,
                               destination_zone=destination_zone,
                               source_ip=source_ip,
                               destination_ip=destination_ip,
                               service=service,
                               to_interface=to_interface,
                               nat_type=nat_type,
                               snat_type=snat_type,
                               snat_address_type=snat_address_type,
                               snat_static_address=snat_static_address,
                               snat_dynamic_address=snat_dynamic_address,
                               snat_interface=snat_interface,
                               snat_interface_address=snat_interface_address,
                               snat_bidirectional=snat_bidirectional,
                               dnat_address=dnat_address,
                               dnat_port=dnat_port)

    if not new_rule:
        module.fail_json(msg='Incorrect NAT rule params specified; quitting')
    parent.add(new_rule)

    # Perform the desired operation.
    changed = False
    do_move = False
    if state == 'present':
        match = find_rule(rules, new_rule)
        if match is not None:
            if not match.equal(new_rule):
                try:
                    new_rule.apply()
                except PanDeviceError as e:
                    module.fail_json(
                        msg='Failed "present" apply: {0}'.format(e))
                else:
                    changed = True
                    do_move = True
        else:
            try:
                new_rule.create()
            except PanDeviceError as e:
                module.fail_json(msg='Failed "present" create: {0}'.format(e))
            else:
                changed = True
                do_move = True
    elif state == 'absent':
        match = find_rule(rules, new_rule)
        if match is not None:
            try:
                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:
            match_dict = xmltodict.parse(match.element_str())
            module.exit_json(stdout_lines=json.dumps(match_dict, indent=2),
                             msg='Rule matched')
        else:
            module.fail_json(
                msg='Rule \'%s\' not found. Is the name correct?' % 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?' % rule_name)
        try:
            new_rule.delete()
        except PanDeviceError as e:
            module.fail_json(msg='Failed "delete" delete: {0}'.format(e))
        else:
            changed = True
    elif operation == "add":
        # Look for required parameters
        if not source_zone or not destination_zone or not nat_type:
            module.fail_json(
                msg=
                'Missing parameter. Required: source_zone, destination_zone, nat_type'
            )
        # 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.'
                % rule_name)
        try:
            new_rule.create()
        except PanDeviceError as e:
            module.fail_json(msg='Failed "add" create: {0}'.format(e))
        else:
            changed = True
            do_move = True
    elif operation == 'update':
        # Search for the rule. Update if found.
        match = find_rule(rulebase, rule_name)
        if not match:
            module.fail_json(
                msg=
                'Rule \'%s\' does not exist. Use operation: \'add\' to add it.'
                % rule_name)
        try:
            new_rule.apply()
        except PanDeviceError as e:
            module.fail_json(msg='Failed "update" apply: {0}'.format(e))
        else:
            changed = True
            do_move = True
    elif operation == 'disable':
        # Search for the rule, disable if found.
        match = find_rule(rules, new_rule)
        if not match:
            module.fail_json(msg='Rule \'%s\' does not exist.' % rule_name)
        if not match.disabled:
            match.disabled = True
            try:
                match.update('disabled')
            except PanDeviceError as e:
                module.fail_json(msg='Failed "disabled": {0}'.format(e))
            else:
                changed = True

    # Optional move.
    if do_move:
        try:
            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

    # Optional commit.
    if changed and commit:
        try:
            con.commit(sync=True)
        except PanDeviceError as e:
            module.fail_json(msg='Failed commit: {0}'.format(e))

    module.exit_json(changed=changed, msg='Done')
Example #25
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')
Example #26
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
Example #27
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),
        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', 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', 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:
                exc = get_exception()
                module.fail_json(msg=exc.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:
                exc = get_exception()
                module.fail_json(msg=exc.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:
                exc = get_exception()
                module.fail_json(msg=exc.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)