Ejemplo n.º 1
0
    def login_as_root(self, domain=None, payload=None):
        """
        This method allows to login into the management server with root permissions.
        In order to use this method the application should be run directly on the management server
        and to have super-user privileges.

        :param domain: [optional] name/uid/IP address of the domain you want to log into in an MDS environment
        :param payload: [optional] dict of additional parameters for the login command
        :return: APIResponse object with the relevant details from the login command.
        """
        python_absolute_path = os.path.expandvars(
            "$MDS_FWDIR/Python/bin/python")
        api_get_port_absolute_path = os.path.expandvars(
            "$MDS_FWDIR/scripts/api_get_port.py")
        mgmt_cli_absolute_path = os.path.expandvars("$CPDIR/bin/mgmt_cli")

        # try to get the management server's port by running a script
        if not self.is_port_default():
            port = self.get_port()
        else:
            try:
                port = compatible_loads(
                    subprocess.check_output([
                        python_absolute_path, api_get_port_absolute_path, "-f",
                        "json"
                    ]))["external_port"]
            # if can't, default back to what the user wrote or the default (443)
            except (ValueError, subprocess.CalledProcessError):
                port = self.get_port()

        try:
            # This simple dict->cli format works only because the login command doesn't require
            # any complex parameters like objects and lists
            new_payload = []
            if payload:
                for key in payload.keys():
                    new_payload += [key, payload[key]]
            if domain:
                new_payload += ["domain", domain]
            login_response = compatible_loads(
                subprocess.check_output([
                    mgmt_cli_absolute_path, "login", "-r", "true", "-f",
                    "json", "--port",
                    str(port)
                ] + new_payload))
            self.sid = login_response["sid"]
            self.server = "127.0.0.1"
            self.domain = domain
            if self.api_version is None:
                self.api_version = login_response["api-server-version"]
            return APIResponse(login_response, success=True)
        except ValueError as err:
            raise APIClientException(
                "Could not load JSON from login as root command, perhaps no root privileges?\n"
                + str(type(err)) + " - " + str(err))
        except (WindowsError, subprocess.CalledProcessError) as err:
            raise APIClientException("Could not login as root:\n" +
                                     str(type(err)) + " - " + str(err))
Ejemplo n.º 2
0
    def __init__(self, json_response, success, status_code=None, err_message=""):
        self.status_code = status_code
        self.data = None

        if err_message:
            self.success = False
            self.error_message = err_message
            self.res_obj = {}
        else:
            self.success = success
            try:
                if isinstance(json_response, dict):
                    data_dict = json_response
                else:
                    data_dict = compatible_loads(json_response)
            except ValueError:
                self.data = {"errors": [{"message": str(json_response)}]}
                self.error_message = "APIResponse received a response which is not a valid JSON."
                self.res_obj = {"status_code": self.status_code, "data": self.data}
            else:
                self.data = data_dict
                self.res_obj = {"status_code": self.status_code, "data": self.data}
                if not self.success:
                    try:
                        self.error_message = extract_error_and_warning_messages(self.data)
                    except KeyError:
                        raise APIException("Unexpected error format.", json_response)
Ejemplo n.º 3
0
Archivo: cli.py Proyecto: aque/cpapi
 def to_obj(self):
     if len(self) == 1 and self[0][0] is Pairs.NO_KEY:
         val = self[0][1]
         if val in {'null', 'true', 'false'} or val[0] in '"{[':
             return compatible_loads(val)
         elif re.match(r'\d+$', val):
             return int(val, 10)
         return val
     pairs = Pairs()
     all_nums = True
     any_nums = False
     for prefix in self.prefixes():
         vals = self.get(prefix)
         if re.match(r'\d+$', prefix):
             prefix = int(prefix, 10)
             any_nums = True
         else:
             all_nums = False
         pairs.add(prefix, vals.to_obj())
     if not all_nums:
         if any_nums:
             raise ValueError('mixed (sub)keys: ["%s"]' % '" "'.join(
                 str(i[0]) for i in pairs))
         return collections.OrderedDict(pairs)
     return [i[1] for i in sorted(pairs)]
Ejemplo n.º 4
0
    def api_call(self,
                 command,
                 payload=None,
                 sid=None,
                 wait_for_task=True,
                 timeout=-1):
        """
        performs a web-service API request to the management server

        :param command: the command is placed in the URL field
        :param payload: a JSON object (or a string representing a JSON object) with the command arguments
        :param sid: [optional]. The Check Point session-id. when omitted use self.sid.
        :param wait_for_task: determines the behavior when the API server responds with a "task-id".
                              by default, the function will periodically check the status of the task
                              and will not return until the task is completed.
                              when wait_for_task=False, it is up to the user to call the "show-task" API and check
                              the status of the command.
        :param timeout: Optional positive timeout (in seconds) before stop waiting for the task even if not completed.
        :return: APIResponse object
        :side-effects: updates the class's uid and server variables
        """
        timeout_start = time.time()

        self.check_fingerprint()
        if payload is None:
            payload = {}
        # Convert the json payload to a string if needed
        if isinstance(payload, str):
            _data = payload
        elif isinstance(payload, dict):
            _data = json.dumps(payload, sort_keys=False)
        else:
            raise TypeError('Invalid payload type - must be dict/string')
        # update class members if needed.
        if sid is None:
            sid = self.sid

        # Set headers
        _headers = {
            "User-Agent": "python-api-wrapper",
            "Accept": "*/*",
            "Content-Type": "application/json",
            "Content-Length": len(_data)
        }

        # In all API calls (except for 'login') a header containing the Check Point session-id is required.
        if sid is not None:
            _headers["X-chkp-sid"] = sid

        # Create ssl context with no ssl verification, we do it by ourselves
        context = ssl.create_default_context()
        context.check_hostname = False
        context.verify_mode = ssl.CERT_NONE

        # create https connection
        if self.proxy_host and self.proxy_port:
            conn = HTTPSConnection(self.proxy_host,
                                   self.proxy_port,
                                   context=context)
            conn.set_tunnel(self.server, self.get_port())
        else:
            conn = HTTPSConnection(self.server,
                                   self.get_port(),
                                   context=context)

        # Set fingerprint
        conn.fingerprint = self.fingerprint

        # Set debug level
        conn.set_debuglevel(self.http_debug_level)
        url = "/" + self.context + "/" + (
            ("v" + str(self.api_version) +
             "/") if self.api_version else "") + command
        response = None
        try:
            # Send the data to the server
            conn.request("POST", url, _data, _headers)
            # Get the reply from the server
            response = conn.getresponse()
            res = APIResponse.from_http_response(response)
        except ValueError as err:
            if err.args[0] == "Fingerprint value mismatch":
                err_message = "Error: Fingerprint value mismatch:\n" + " Expecting : {}\n".format(
                    err.args[1]
                ) + " Got: {}\n".format(
                    err.args[2]
                ) + "If you trust the new fingerprint, edit the 'fingerprints.txt' file."
                res = APIResponse("", False, err_message=err_message)
            else:
                res = APIResponse("", False, err_message=err)
        except Exception as err:
            res = APIResponse("", False, err_message=err)
        finally:
            conn.close()

        if response:
            res.status_code = response.status

        # When the command is 'login' we'd like to convert the password to "****" so that it
        # would not appear as plaintext in the debug file.
        if command == "login":
            json_data = compatible_loads(_data)
            json_data["password"] = "******"
            _data = json.dumps(json_data)

        # Store the request and the reply (for debug purpose).
        _api_log = {
            "request": {
                "url": url,
                "payload": compatible_loads(_data),
                "headers": _headers
            },
            "response": res.response()
        }
        self.api_calls.append(_api_log)

        # If we want to wait for the task to end, wait for it
        if wait_for_task is True and res.success and command != "show-task":
            if "task-id" in res.data:
                res = self.__wait_for_task(res.data["task-id"],
                                           timeout=(timeout - time.time() +
                                                    timeout_start))
            elif "tasks" in res.data:
                res = self.__wait_for_tasks(res.data["tasks"],
                                            timeout=(timeout - time.time() +
                                                     timeout_start))

        return res
Ejemplo n.º 5
0
Archivo: cli.py Proyecto: aque/cpapi
def main(argv):
    NO_DEFAULT = object()
    parser = argparse.ArgumentParser(prog=argv[0])
    parser.add_argument(
        '--format', '-f', metavar='{json|text}', nargs=1, default='text',
        action=Format)
    args_def = [
        ('--debug', None, '{on|off}', 'MGMT_CLI_DEBUG'),
        ('--domain', '-d', 'DOMAIN', 'MGMT_CLI_DOMAIN'),
        ('--fingerprint', None, 'FINGERPRINT', 'MGMT_CLI_FINGERPRINT'),
        ('--management', '-m', 'SERVER', 'MGMT_CLI_MANAGEMENT'),
        ('--password', '-p', 'PASSWORD', 'MGMT_CLI_PASSWORD'),
        ('--port', None, 'PORT', 'MGMT_CLI_PORT'),
        ('--proxy', '-x', 'PROXY', 'MGMT_CLI_PROXY'),
        ('--root', '-r', '{true|false}', None),
        ('--session-id', None, 'SESSION-ID', 'MGMT_CLI_SESSION_ID'),
        ('--sync', None, '{true|false}', 'MGMT_CLI_SYNC'),
        ('--user', '-u', 'USER', 'MGMT_CLI_USER'),
        ('--version', '-v', 'VERSION', 'MGMT_CLI_VERSION'),
    ]
    for lname, sname, meta, env in args_def:
        pargs = [lname]
        if sname:
            pargs.append(sname)
        kwargs = {'metavar': meta}
        if env:
            kwargs['default'] = os.environ.get(env, NO_DEFAULT)
        else:
            kwargs['default'] = NO_DEFAULT
        parser.add_argument(*pargs, **kwargs)
    parser.add_argument('command', metavar='COMMAND')
    parser.add_argument('arg', metavar='ARG', nargs='*', action=Args)
    argv = preprocess_argv(argv)
    if argv is None:
        return
    args = parser.parse_args(args=argv[1:])
    for lname, _, _, _ in args_def:
        attr = lname[2:].replace('-', '_')
        if getattr(args, attr, None) is NO_DEFAULT:
            delattr(args, attr)
    client_args = {}
    if getattr(args, 'debug', 'off') == 'on':
        log.debug = True
        client_args['debug_file'] = sys.stderr  # dummy
        # FIXME: remove when save_debug_data is fixed
        APIClient.save_debug_data = lambda self: sys.stderr.write(
            'API calls: %s\n' % json.dumps(self.api_calls, indent=2))
        client_args['http_debug_level'] = 1
    debug('args: %s\n' % args)
    if hasattr(args, 'port'):
        args.port = int(args.port)
    if hasattr(args, 'proxy'):
        args.proxy_host, _, port = args.proxy.partition(':')
        if '@' in args.proxy_host:
            raise Exception('proxy authentication is not implemented')
        if port:
            args.proxy_port = int(port)
    clargs_def = [
        ('management', 'server'),
        ('port', None),
        ('fingerprint', None),
        ('proxy_host', None),
        ('proxy_port', None),
    ]
    for name, cla in clargs_def:
        val = getattr(args, name, None)
        if cla is None:
            cla = name
        if val is not None:
            client_args[cla] = val
    debug('client args: %s\n' % client_args)
    args.domain = getattr(args, 'domain', None)
    args.root = compatible_loads(getattr(args, 'root', 'false'))
    args.sync = compatible_loads(getattr(args, 'sync', 'true'))
    with APIClient(APIClientArgs(**client_args)) as client:
        call_args = {}
        if hasattr(args, 'session_id'):
            call_args['sid'] = args.session_id
        elif args.root:
            client.login_as_root(domain=args.domain)
        elif hasattr(args, 'password') and args.command != 'login':
            client.login(username=args.user, password=args.password,
                         domain=args.domain)
        if hasattr(args, 'version'):
            # FIXME: remove when api_call accepts api_version
            client.api_version = args.version
        saved_stdout = sys.stdout
        publish_response = None
        try:
            sys.stdout = sys.stderr
            if args.command == 'login':
                for attr in ('user', 'password', 'domain'):
                    if attr not in args.arg:
                        val = getattr(args, attr, None)
                        if val:
                            args.arg[attr] = val
            response = client.api_call(
                args.command, args.arg, wait_for_task=args.sync,
                **call_args).as_dict()
            if any(args.command.startswith(p) for p in {
                    'set-', 'add-', 'delete-', 'get-interfaces'}):
                publish_response = client.api_call(
                    'publish', {}, wait_for_task=args.sync).as_dict()
        finally:
            sys.stdout = saved_stdout
    if not response.get('success'):
        raise Exception(json.dumps(response, indent=2))
    if publish_response and not publish_response.get('success'):
        raise Exception(json.dumps(publish_response, indent=2))
    sys.stdout.write(args.format(response.get('data')))