Ejemplo n.º 1
0
    def _get_conn_info(self, param):
        if 'conn_id' not in param:
            return self.write_json(TPE_PARAM)

        conn_id = param['conn_id']
        x = tp_session().taken('tmp-conn-info-{}'.format(conn_id), None)
        if x is None:
            return self.write_json(TPE_NOT_EXISTS)
        else:
            return self.write_json(TPE_OK, data=x)
Ejemplo n.º 2
0
    def open(self, sid):
        # 处理新的连接
        k = '{}-{}'.format('user', sid)
        _user = tp_session().get(k, None)
        if _user is None:
            ret = {'code': TPE_NEED_LOGIN, 'message': '需要登录'}
            self.write_message(json.dumps(ret))
            return

        tp_wss().register(self)
Ejemplo n.º 3
0
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_USER_DELETE)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            action = args['action']
            users = args['users']
        except:
            return self.write_json(TPE_PARAM)

        if action == 'lock':
            err = user.update_users_state(self, users, TP_STATE_DISABLED)
        elif action == 'unlock':
            err = user.update_users_state(self, users, TP_STATE_NORMAL)
        elif action == 'remove':
            err = user.remove_users(self, users)
        else:
            err = TPE_PARAM

        if err != TPE_OK:
            return self.write_json(err)

        # force logout if user LOCKED or REMOVED.
        if action == 'lock' or action == 'remove':
            v = tp_session().get_start_with('user-')
            for k in v:
                if v[k]['v']['id'] in users:
                    tp_session().taken(k)

        self.write_json(err)
Ejemplo n.º 4
0
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_USER_DELETE)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            action = args['action']
            users = args['users']
        except:
            return self.write_json(TPE_PARAM)

        if action == 'lock':
            err = user.update_users_state(self, users, TP_STATE_DISABLED)
        elif action == 'unlock':
            err = user.update_users_state(self, users, TP_STATE_NORMAL)
        elif action == 'remove':
            err = user.remove_users(self, users)
        else:
            err = TPE_PARAM

        if err != TPE_OK:
            return self.write_json(err)

        # force logout if user LOCKED or REMOVED.
        if action == 'lock' or action == 'remove':
            v = tp_session().get_start_with('user-')
            for k in v:
                if v[k]['v']['id'] in users:
                    tp_session().taken(k)

        self.write_json(err)
Ejemplo n.º 5
0
    def run(self):
        log.i('\n')
        log.i(
            '###############################################################\n'
        )
        log.i('Load config file: {}\n'.format(self._cfg_file))
        log.i('Teleport Web Server starting ...\n')

        # 尝试通过CORE-JSON-RPC获取core服务的配置(主要是ssh/rdp/telnet的端口以及录像文件存放路径)
        # self._get_core_server_config()

        _db = get_db()
        if not _db.init():
            log.e('can not initialize database interface.\n')
            return 0

        _db.connect()
        while not _db.connected:
            log.w('database not connected, retry after 5 seconds.\n')
            time.sleep(5)
            _db.connect()

        cfg = tp_cfg()

        _db.check_status()
        if _db.need_create or _db.need_upgrade:
            cfg.app_mode = APP_MODE_MAINTENANCE
        else:
            cfg.app_mode = APP_MODE_NORMAL

        if not tp_session().init():
            log.e('can not initialize session manager.\n')
            return 0
        # if not tp_stats().init():
        #     log.e('can not initialize system status collector.\n')
        #     return 0

        settings = {
            #
            'cookie_secret': '8946svdABGD345fg98uhIaefEBePIfegOIakjFH43oETzK',
            'login_url': '/auth/login',

            # 指定静态文件的路径,页面模板中可以用 {{ static_url('css/main.css') }} 的方式调用
            'static_path': cfg.static_path,

            # 指定模板文件的路径
            'template_path': cfg.template_path,

            # 防止跨站伪造请求,参见 http://old.sebug.net/paper/books/tornado/#_7
            'xsrf_cookies': False,
            'autoescape': 'xhtml_escape',

            # 'ui_modules': ui_modules,
            'debug': False,

            # 不开启模板和静态文件的缓存,这样一旦模板文件和静态文件变化,刷新浏览器即可看到更新。
            'compiled_template_cache': False,
            'static_hash_cache': False,
        }

        from app.controller import controllers
        _app = tornado.web.Application(controllers, **settings)

        server = tornado.httpserver.HTTPServer(_app, xheaders=True)
        # server = tornado.httpserver.HTTPServer(_app, ssl_options={
        #     "certfile": os.path.join(cfg.data_path, 'cert', "server.pem"),
        #     "keyfile": os.path.join(cfg.data_path, 'cert', "server.key"),
        # })

        try:
            server.listen(cfg.common.port, address=cfg.common.ip)
            if cfg.common.ip == '0.0.0.0':
                log.i('works on [http://127.0.0.1:{}]\n'.format(
                    cfg.common.port))
            else:
                log.i('works on [http://{}:{}]\n'.format(
                    cfg.common.ip, cfg.common.port))
        except:
            log.e(
                'can not listen on port {}:{}, make sure it not been used by another application.\n'
                .format(cfg.common.ip, cfg.common.port))
            return 0

        try:
            tornado.ioloop.IOLoop.instance().start()
        except:
            log.e('\n')

        return 0
Ejemplo n.º 6
0
 def del_session(self, name):
     k = '{}-{}'.format(name, self._s_id)
     return tp_session().set(k, '', -1)
Ejemplo n.º 7
0
 def get_session(self, name, _default=None):
     k = '{}-{}'.format(name, self._s_id)
     return tp_session().get(k, _default)
Ejemplo n.º 8
0
 def set_session(self, name, value, expire=None):
     k = '{}-{}'.format(name, self._s_id)
     tp_session().set(k, value, expire)
Ejemplo n.º 9
0
    def post(self):
        # ret = self.check_privilege(TP_PRIVILEGE_ASSET_CREATE | TP_PRIVILEGE_ASSET_DELETE | TP_PRIVILEGE_OPS | TP_PRIVILEGE_OPS_AUZ)
        # if ret != TPE_OK:
        #     return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        # 有三种方式获取会话ID:
        # 1. 给定一个远程连接授权ID(普通用户进行远程连接)
        # 2. 给定要连接的主机ID和账号ID(管理员进行远程连接)
        # 3. 给定要连接的主机ID和账号信息(管理员测试远程连接是否可用)
        #
        # WEB服务根据上述信息产生临时的远程连接ID,核心服务通过此远程连接ID来获取远程连接所需数据,生成会话ID。

        try:
            _mode = int(args['mode'])
            _protocol_type = int(args['protocol_type'])
            _protocol_sub_type = int(args['protocol_sub_type'])
        except:
            return self.write_json(TPE_PARAM)

        conn_info = dict()
        conn_info['_enc'] = 1
        conn_info['host_id'] = 0
        conn_info['client_ip'] = self.request.remote_ip
        conn_info['user_id'] = self.get_current_user()['id']
        conn_info['user_username'] = self.get_current_user()['username']

        # mode = 0:  test connect
        # mode = 1:  user connect
        # mode = 2:  admin connect
        if _mode == 1:
            # 通过指定的auth_id连接(需要授权),必须具有远程运维的权限方可进行
            ret = self.check_privilege(TP_PRIVILEGE_OPS)
            if ret != TPE_OK:
                return

            if 'auth_id' not in args or 'protocol_sub_type' not in args:
                return self.write_json(TPE_PARAM)

            # 根据auth_id从数据库中取得此授权相关的用户、主机、账号三者详细信息
            auth_id = args['auth_id']
            ops_auth, err = ops.get_auth(auth_id)
            if err != TPE_OK:
                return self.write_json(err)

            policy_id = ops_auth['p_id']
            acc_id = ops_auth['a_id']
            host_id = ops_auth['h_id']

            err, policy_info = ops.get_by_id(policy_id)
            if err != TPE_OK:
                return self.write_json(err)

            err, acc_info = account.get_account_info(acc_id)
            if err != TPE_OK:
                return self.write_json(err)
            # log.v(acc_info)

            if acc_info['protocol_type'] == TP_PROTOCOL_TYPE_RDP:
                acc_info['protocol_flag'] = policy_info['flag_rdp']
            elif acc_info['protocol_type'] == TP_PROTOCOL_TYPE_SSH:
                acc_info['protocol_flag'] = policy_info['flag_ssh']
            elif acc_info['protocol_type'] == TP_PROTOCOL_TYPE_TELNET:
                acc_info['protocol_flag'] = policy_info['flag_telnet']
            else:
                acc_info['protocol_flag'] = 0
            acc_info['record_flag'] = policy_info['flag_record']

        elif _mode == 2:
            # 直接连接(无需授权),必须具有运维授权管理的权限方可进行
            ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
            if ret != TPE_OK:
                return

            acc_id = args['acc_id']
            host_id = args['host_id']

            err, acc_info = account.get_account_info(acc_id)
            if err != TPE_OK:
                return self.write_json(err)

            acc_info['protocol_flag'] = TP_FLAG_ALL
            acc_info['record_flag'] = TP_FLAG_ALL

        elif _mode == 0:
            # 测试连接,必须具有主机信息创建、编辑的权限方可进行
            ret = self.check_privilege(TP_PRIVILEGE_ASSET_CREATE)
            if ret != TPE_OK:
                return

            conn_info['_test'] = 1
            try:
                acc_id = int(args['acc_id'])
                host_id = int(args['host_id'])
                auth_type = int(args['auth_type'])
                username = args['username']
                password = args['password']
                pri_key = args['pri_key']
                protocol_port = int(args['protocol_port'])
                username_prompt = args['username_prompt']
                password_prompt = args['password_prompt']
            except:
                return self.write_json(TPE_PARAM)

            if len(username) == 0:
                return self.write_json(TPE_PARAM)

            acc_info = dict()

            acc_info['auth_type'] = auth_type
            acc_info['protocol_type'] = _protocol_type
            acc_info['protocol_port'] = protocol_port
            acc_info['protocol_flag'] = TP_FLAG_ALL
            acc_info['record_flag'] = TP_FLAG_ALL
            acc_info['username'] = username

            acc_info['password'] = password
            acc_info['pri_key'] = pri_key

            acc_info['username_prompt'] = username_prompt
            acc_info['password_prompt'] = password_prompt

            conn_info['_enc'] = 0

            if acc_id == -1:
                if auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0:
                    return self.write_json(TPE_PARAM)
                elif auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(
                        pri_key) == 0:
                    return self.write_json(TPE_PARAM)
            else:
                if (auth_type == TP_AUTH_TYPE_PASSWORD and len(password)
                        == 0) or (auth_type == TP_AUTH_TYPE_PRIVATE_KEY
                                  and len(pri_key) == 0):
                    err, _acc_info = account.get_account_info(acc_id)
                    if err != TPE_OK:
                        return self.write_json(err)
                    acc_info['password'] = _acc_info['password']
                    acc_info['pri_key'] = _acc_info['pri_key']

                    conn_info['_enc'] = 1

        else:
            return self.write_json(TPE_PARAM)

        # 获取要远程连接的主机信息(要访问的IP地址,如果是路由模式,则是路由主机的IP+端口)
        err, host_info = host.get_host_info(host_id)
        if err != TPE_OK:
            return self.write_json(err)

        conn_info['host_id'] = host_id
        conn_info['host_ip'] = host_info['ip']
        if len(host_info['router_ip']) > 0:
            conn_info['conn_ip'] = host_info['router_ip']
            conn_info['conn_port'] = host_info['router_port']
        else:
            conn_info['conn_ip'] = host_info['ip']
            conn_info['conn_port'] = acc_info['protocol_port']

        conn_info['acc_id'] = acc_id
        conn_info['acc_username'] = acc_info['username']
        conn_info['username_prompt'] = acc_info['username_prompt']
        conn_info['password_prompt'] = acc_info['password_prompt']
        conn_info['protocol_flag'] = acc_info['protocol_flag']
        conn_info['record_flag'] = acc_info['record_flag']

        conn_info['protocol_type'] = acc_info['protocol_type']
        conn_info['protocol_sub_type'] = _protocol_sub_type

        conn_info['auth_type'] = acc_info['auth_type']
        if acc_info['auth_type'] == TP_AUTH_TYPE_PASSWORD:
            conn_info['acc_secret'] = acc_info['password']
        elif acc_info['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY:
            conn_info['acc_secret'] = acc_info['pri_key']
        else:
            conn_info['acc_secret'] = ''

        with tmp_conn_id_lock:
            global tmp_conn_id_base
            tmp_conn_id_base += 1
            conn_id = tmp_conn_id_base

        # log.v('CONN-INFO:', conn_info)
        tp_session().set('tmp-conn-info-{}'.format(conn_id), conn_info, 10)

        req = {'method': 'request_session', 'param': {'conn_id': conn_id}}
        _yr = core_service_async_post_http(req)
        _code, ret_data = yield _yr
        if _code != TPE_OK:
            return self.write_json(_code)
        if ret_data is None:
            return self.write_json(TPE_FAILED, '调用核心服务获取会话ID失败')

        if 'sid' not in ret_data:
            return self.write_json(TPE_FAILED, '核心服务获取会话ID时返回错误数据')

        data = dict()
        data['session_id'] = ret_data['sid']
        data['host_ip'] = host_info['ip']
        data['protocol_flag'] = acc_info['protocol_flag']

        if conn_info['protocol_type'] == TP_PROTOCOL_TYPE_RDP:
            data['teleport_port'] = tp_cfg().core.rdp.port
        elif conn_info['protocol_type'] == TP_PROTOCOL_TYPE_SSH:
            data['teleport_port'] = tp_cfg().core.ssh.port
        elif conn_info['protocol_type'] == TP_PROTOCOL_TYPE_TELNET:
            data['teleport_port'] = tp_cfg().core.telnet.port

        return self.write_json(0, data=data)
Ejemplo n.º 10
0
    def _run_loop(self):
        ext_srv_cfg = tp_ext_srv_cfg()
        if not ext_srv_cfg.init():
            return 0

        log.i('Teleport Web Server starting ...\n')

        tp_cron().init()

        # 尝试通过CORE-JSON-RPC获取core服务的配置(主要是ssh/rdp/telnet的端口以及录像文件存放路径)
        self._get_core_server_config()

        _db = get_db()
        if not _db.init():
            log.e('can not initialize database interface.\n')
            return 0

        _db.connect()
        while not _db.connected:
            log.w('database not connected, retry after 5 seconds.\n')
            time.sleep(5)
            _db.connect()

        cfg = tp_cfg()

        _db.check_status()
        if _db.need_create or _db.need_upgrade:
            cfg.app_mode = APP_MODE_MAINTENANCE
            tp_cfg().update_sys(None)
        else:
            cfg.app_mode = APP_MODE_NORMAL
            _db.load_system_config()

        try:
            # 将运行时配置发送给核心服务
            req = {'method': 'set_config', 'param': {'noop_timeout': tp_cfg().sys.session.noop_timeout}}
            req_data = json.dumps(req)
            data = urllib.parse.quote(req_data).encode('utf-8')
            req = urllib.request.Request(url=cfg.common.core_server_rpc, data=data)
            rep = urllib.request.urlopen(req, timeout=3)
            body = rep.read().decode()
            x = json.loads(body)
            if 'code' not in x or x['code'] != 0:
                print(x)
                log.e('connect core-server for set runtime-config failed.\n')
            else:
                log.d('set runtime-config for core-server succeeded.\n')
        except:
            log.w('can not connect to core-server to set runtime-config, maybe it not start yet, ignore.\n')

        if not tp_session().init():
            log.e('can not initialize session manager.\n')
            return 0

        if not tp_stats().init():
            log.e('can not initialize system status collector.\n')
            return 0

        if cfg.common.check_host_alive:
            if not tp_host_alive().init():
                log.e('can not initialize host state inspector.\n')
                return 0

        settings = {
            #
            'cookie_secret': '8946svdABGD345fg98uhIaefEBePIfegOIakjFH43oETzK',

            'login_url': '/auth/login',

            # 指定静态文件的路径,页面模板中可以用 {{ static_url('css/main.css') }} 的方式调用
            'static_path': cfg.static_path,

            # 指定模板文件的路径
            'template_path': cfg.template_path,

            # 防止跨站伪造请求,参见 http://old.sebug.net/paper/books/tornado/#_7
            'xsrf_cookies': False,

            'autoescape': 'xhtml_escape',

            # 'ui_modules': ui_modules,
            'debug': False,

            # 不开启模板和静态文件的缓存,这样一旦模板文件和静态文件变化,刷新浏览器即可看到更新。
            'compiled_template_cache': False,
            'static_hash_cache': False,
        }

        from app.controller import controllers, fix_controller
        fix_controller()
        _app = tornado.web.Application(controllers, **settings)

        server = tornado.httpserver.HTTPServer(_app, xheaders=True)
        # server = tornado.httpserver.HTTPServer(_app, xheaders=True, ssl_options={
        #     "certfile": os.path.join(cfg.data_path, 'cert', "server.pem"),
        #     "keyfile": os.path.join(cfg.data_path, 'cert', "server.key"),
        # })

        try:
            server.listen(cfg.common.port, address=cfg.common.ip)
            if cfg.common.ip == '0.0.0.0':
                log.i('works on [http://127.0.0.1:{}]\n'.format(cfg.common.port))
            else:
                log.i('works on [http://{}:{}]\n'.format(cfg.common.ip, cfg.common.port))
        except:
            log.e('can not listen on port {}:{}, make sure it not been used by another application.\n'.format(cfg.common.ip, cfg.common.port))
            return 0

        # 启动定时任务调度器
        tp_cron().start()

        try:
            tornado.ioloop.IOLoop.instance().start()
        except:
            log.e('\n')

        if tp_cfg().common.check_host_alive:
            tp_host_alive().stop()
        tp_cron().stop()
        return 0
Ejemplo n.º 11
0
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            processed = False
            if 'smtp' in args:
                processed = True
                _cfg = args['smtp']
                _server = _cfg['server']
                _port = _cfg['port']
                _ssl = _cfg['ssl']
                _sender = _cfg['sender']
                _password = _cfg['password']

                # TODO: encrypt the password before save by core-service.
                # TODO: if not send password, use pre-saved password.

                err = system_model.save_config(self, '更新SMTP设置', 'smtp', _cfg)
                if err == TPE_OK:
                    # 同时更新内存缓存
                    tp_cfg().sys.smtp.server = _server
                    tp_cfg().sys.smtp.port = _port
                    tp_cfg().sys.smtp.ssl = _ssl
                    tp_cfg().sys.smtp.sender = _sender
                    # 特殊处理,防止前端拿到密码
                    tp_cfg().sys_smtp_password = _password
                else:
                    return self.write_json(err)            
            
            #增加urlprotocol的配置		
            if 'global' in args:
                processed = True
                _cfg = args['global']
                _url_proto = _cfg['url_proto']
                
                err = system_model.save_config(self, '更新全局设置', 'global', _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.glob.url_proto = _url_proto
                else:
                    return self.write_json(err)
            

            if 'password' in args:
                processed = True
                _cfg = args['password']
                _allow_reset = _cfg['allow_reset']
                _force_strong = _cfg['force_strong']
                _timeout = _cfg['timeout']
                err = system_model.save_config(self, '更新密码策略设置', 'password', _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.password.allow_reset = _allow_reset
                    tp_cfg().sys.password.force_strong = _force_strong
                    tp_cfg().sys.password.timeout = _timeout
                else:
                    return self.write_json(err)

            if 'login' in args:
                processed = True
                _cfg = args['login']
                _session_timeout = _cfg['session_timeout']
                _retry = _cfg['retry']
                _lock_timeout = _cfg['lock_timeout']
                _auth = _cfg['auth']
                err = system_model.save_config(self, '更新登录策略设置', 'login', _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.login.session_timeout = _session_timeout
                    tp_cfg().sys.login.retry = _retry
                    tp_cfg().sys.login.lock_timeout = _lock_timeout
                    tp_cfg().sys.login.auth = _auth
                    tp_session().update_default_expire()
                else:
                    return self.write_json(err)

            if 'session' in args:
                processed = True
                _cfg = args['session']
                _noop_timeout = _cfg['noop_timeout']
                _flag_record = _cfg['flag_record']
                _flag_rdp = _cfg['flag_rdp']
                _flag_ssh = _cfg['flag_ssh']
                err = system_model.save_config(self, '更新连接控制设置', 'session', _cfg)
                if err == TPE_OK:
                    try:
                        req = {'method': 'set_config', 'param': {'noop_timeout': _noop_timeout}}
                        _yr = core_service_async_post_http(req)
                        code, ret_data = yield _yr
                        if code != TPE_OK:
                            log.e('can not set runtime-config to core-server.\n')
                            return self.write_json(code)
                    except:
                        pass

                    tp_cfg().sys.session.noop_timeout = _noop_timeout
                    tp_cfg().sys.session.flag_record = _flag_record
                    tp_cfg().sys.session.flag_rdp = _flag_rdp
                    tp_cfg().sys.session.flag_ssh = _flag_ssh
                else:
                    return self.write_json(err)

            if 'storage' in args:
                processed = True
                _cfg = args['storage']
                _keep_log = _cfg['keep_log']
                _keep_record = _cfg['keep_record']
                _cleanup_hour = _cfg['cleanup_hour']
                _cleanup_minute = _cfg['cleanup_minute']

                if not ((30 <= _keep_log <= 365) or _keep_log == 0):
                    return self.write_json(TPE_PARAM, '系统日志保留时间超出范围!')
                if not ((30 <= _keep_record <= 365) or _keep_record == 0):
                    return self.write_json(TPE_PARAM, '会话录像保留时间超出范围!')

                err = system_model.save_config(self, '更新存储策略设置', 'storage', _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.storage.keep_log = _keep_log
                    tp_cfg().sys.storage.keep_record = _keep_record
                    tp_cfg().sys.storage.cleanup_hour = _cleanup_hour
                    tp_cfg().sys.storage.cleanup_minute = _cleanup_minute
                else:
                    return self.write_json(err)

            if 'ldap' in args:
                processed = True
                _cfg = args['ldap']
                # _password = _cfg['password']
                _server = _cfg['server']
                _port = _cfg['port']
                _domain = _cfg['domain']
                _admin = _cfg['admin']
                _base_dn = _cfg['base_dn']
                _filter = _cfg['filter']
                _attr_username = _cfg['attr_username']
                _attr_surname = _cfg['attr_surname']
                _attr_email = _cfg['attr_email']

                if len(_cfg['password']) == 0:
                    _cfg['password'] = tp_cfg().sys_ldap_password

                if len(_cfg['password']) == 0:
                    return self.write_json(TPE_PARAM, '请设置LDAP管理员密码')

                # TODO: encrypt the password before save by core-service.

                err = system_model.save_config(self, '更新LDAP设置', 'ldap', _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.ldap.server = _server
                    tp_cfg().sys.ldap.port = _port
                    tp_cfg().sys.ldap.domain = _domain
                    tp_cfg().sys.ldap.admin = _admin
                    tp_cfg().sys.ldap.base_dn = _base_dn
                    tp_cfg().sys.ldap.filter = _filter
                    tp_cfg().sys.ldap.attr_username = _attr_username
                    tp_cfg().sys.ldap.attr_surname = _attr_surname
                    tp_cfg().sys.ldap.attr_email = _attr_email
                    # 特殊处理,防止前端拿到密码
                    tp_cfg().sys_ldap_password = _cfg['password']
                else:
                    return self.write_json(err)

            if not processed:
                return self.write_json(TPE_PARAM)

            return self.write_json(TPE_OK)
        except:
            log.e('\n')
            self.write_json(TPE_FAILED)
Ejemplo n.º 12
0
    def post(self):
        # ret = self.check_privilege(TP_PRIVILEGE_ASSET_CREATE | TP_PRIVILEGE_ASSET_DELETE | TP_PRIVILEGE_OPS | TP_PRIVILEGE_OPS_AUZ)
        # if ret != TPE_OK:
        #     return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        # 有三种方式获取会话ID:
        # 1. 给定一个远程连接授权ID(普通用户进行远程连接)
        # 2. 给定要连接的主机ID和账号ID(管理员进行远程连接)
        # 3. 给定要连接的主机ID和账号信息(管理员测试远程连接是否可用)
        #
        # WEB服务根据上述信息产生临时的远程连接ID,核心服务通过此远程连接ID来获取远程连接所需数据,生成会话ID。

        try:
            _mode = int(args['mode'])
            _protocol_type = int(args['protocol_type'])
            _protocol_sub_type = int(args['protocol_sub_type'])
        except:
            return self.write_json(TPE_PARAM)

        conn_info = dict()
        conn_info['_enc'] = 1
        conn_info['host_id'] = 0
        conn_info['client_ip'] = self.request.remote_ip
        conn_info['user_id'] = self.get_current_user()['id']
        conn_info['user_username'] = self.get_current_user()['username']

        # mode = 0:  test connect
        # mode = 1:  user connect
        # mode = 2:  admin connect
        if _mode == 1:
            # 通过指定的auth_id连接(需要授权),必须具有远程运维的权限方可进行
            ret = self.check_privilege(TP_PRIVILEGE_OPS)
            if ret != TPE_OK:
                return

            if 'auth_id' not in args or 'protocol_sub_type' not in args:
                return self.write_json(TPE_PARAM)

            # 根据auth_id从数据库中取得此授权相关的用户、主机、账号三者详细信息
            auth_id = args['auth_id']
            ops_auth, err = ops.get_auth(auth_id)
            if err != TPE_OK:
                return self.write_json(err)

            policy_id = ops_auth['p_id']
            acc_id = ops_auth['a_id']
            host_id = ops_auth['h_id']

            err, policy_info = ops.get_by_id(policy_id)
            if err != TPE_OK:
                return self.write_json(err)

            err, acc_info = account.get_account_info(acc_id)
            if err != TPE_OK:
                return self.write_json(err)
            # log.v(acc_info)

            if acc_info['protocol_type'] == TP_PROTOCOL_TYPE_RDP:
                acc_info['protocol_flag'] = policy_info['flag_rdp']
            elif acc_info['protocol_type'] == TP_PROTOCOL_TYPE_SSH:
                acc_info['protocol_flag'] = policy_info['flag_ssh']
            elif acc_info['protocol_type'] == TP_PROTOCOL_TYPE_TELNET:
                acc_info['protocol_flag'] = policy_info['flag_telnet']
            else:
                acc_info['protocol_flag'] = 0
            acc_info['record_flag'] = policy_info['flag_record']

        elif _mode == 2:
            # 直接连接(无需授权),必须具有运维授权管理的权限方可进行
            ret = self.check_privilege(TP_PRIVILEGE_OPS_AUZ)
            if ret != TPE_OK:
                return

            acc_id = args['acc_id']
            host_id = args['host_id']

            err, acc_info = account.get_account_info(acc_id)
            if err != TPE_OK:
                return self.write_json(err)

            acc_info['protocol_flag'] = TP_FLAG_ALL
            acc_info['record_flag'] = TP_FLAG_ALL

        elif _mode == 0:
            # 测试连接,必须具有主机信息创建、编辑的权限方可进行
            ret = self.check_privilege(TP_PRIVILEGE_ASSET_CREATE)
            if ret != TPE_OK:
                return

            conn_info['_test'] = 1
            try:
                acc_id = int(args['acc_id'])
                host_id = int(args['host_id'])
                auth_type = int(args['auth_type'])
                username = args['username']
                password = args['password']
                pri_key = args['pri_key']
                protocol_port = int(args['protocol_port'])
                username_prompt = args['username_prompt']
                password_prompt = args['password_prompt']
            except:
                return self.write_json(TPE_PARAM)

            if len(username) == 0:
                return self.write_json(TPE_PARAM)

            acc_info = dict()

            acc_info['auth_type'] = auth_type
            acc_info['protocol_type'] = _protocol_type
            acc_info['protocol_port'] = protocol_port
            acc_info['protocol_flag'] = TP_FLAG_ALL
            acc_info['record_flag'] = TP_FLAG_ALL
            acc_info['username'] = username

            acc_info['password'] = password
            acc_info['pri_key'] = pri_key

            acc_info['username_prompt'] = username_prompt
            acc_info['password_prompt'] = password_prompt

            conn_info['_enc'] = 0

            if acc_id == -1:
                if auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0:
                    return self.write_json(TPE_PARAM)
                elif auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(pri_key) == 0:
                    return self.write_json(TPE_PARAM)
            else:
                if (auth_type == TP_AUTH_TYPE_PASSWORD and len(password) == 0) or (auth_type == TP_AUTH_TYPE_PRIVATE_KEY and len(pri_key) == 0):
                    err, _acc_info = account.get_account_info(acc_id)
                    if err != TPE_OK:
                        return self.write_json(err)
                    acc_info['password'] = _acc_info['password']
                    acc_info['pri_key'] = _acc_info['pri_key']

                    conn_info['_enc'] = 1

        else:
            return self.write_json(TPE_PARAM)

        # 获取要远程连接的主机信息(要访问的IP地址,如果是路由模式,则是路由主机的IP+端口)
        err, host_info = host.get_host_info(host_id)
        if err != TPE_OK:
            return self.write_json(err)

        conn_info['host_id'] = host_id
        conn_info['host_ip'] = host_info['ip']
        if len(host_info['router_ip']) > 0:
            conn_info['conn_ip'] = host_info['router_ip']
            conn_info['conn_port'] = host_info['router_port']
        else:
            conn_info['conn_ip'] = host_info['ip']
            conn_info['conn_port'] = acc_info['protocol_port']

        conn_info['acc_id'] = acc_id
        conn_info['acc_username'] = acc_info['username']
        conn_info['username_prompt'] = acc_info['username_prompt']
        conn_info['password_prompt'] = acc_info['password_prompt']
        conn_info['protocol_flag'] = acc_info['protocol_flag']
        conn_info['record_flag'] = acc_info['record_flag']

        conn_info['protocol_type'] = acc_info['protocol_type']
        conn_info['protocol_sub_type'] = _protocol_sub_type

        conn_info['auth_type'] = acc_info['auth_type']
        if acc_info['auth_type'] == TP_AUTH_TYPE_PASSWORD:
            conn_info['acc_secret'] = acc_info['password']
        elif acc_info['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY:
            conn_info['acc_secret'] = acc_info['pri_key']
        else:
            conn_info['acc_secret'] = ''

        with tmp_conn_id_lock:
            global tmp_conn_id_base
            tmp_conn_id_base += 1
            conn_id = tmp_conn_id_base

        # log.v('CONN-INFO:', conn_info)
        tp_session().set('tmp-conn-info-{}'.format(conn_id), conn_info, 10)

        req = {'method': 'request_session', 'param': {'conn_id': conn_id}}
        _yr = core_service_async_post_http(req)
        _code, ret_data = yield _yr
        if _code != TPE_OK:
            return self.write_json(_code)
        if ret_data is None:
            return self.write_json(TPE_FAILED, '调用核心服务获取会话ID失败')

        if 'sid' not in ret_data:
            return self.write_json(TPE_FAILED, '核心服务获取会话ID时返回错误数据')

        data = dict()
        data['session_id'] = ret_data['sid']
        data['host_ip'] = host_info['ip']
        data['protocol_flag'] = acc_info['protocol_flag']

        if conn_info['protocol_type'] == TP_PROTOCOL_TYPE_RDP:
            data['teleport_port'] = tp_cfg().core.rdp.port
        elif conn_info['protocol_type'] == TP_PROTOCOL_TYPE_SSH:
            data['teleport_port'] = tp_cfg().core.ssh.port
        elif conn_info['protocol_type'] == TP_PROTOCOL_TYPE_TELNET:
            data['teleport_port'] = tp_cfg().core.telnet.port

        return self.write_json(0, data=data)
Ejemplo n.º 13
0
    def run(self):
        log.i('\n')
        log.i('###############################################################\n')
        log.i('Load config file: {}\n'.format(self._cfg_file))
        log.i('Teleport Web Server starting ...\n')

        tp_cron().init()

        # 尝试通过CORE-JSON-RPC获取core服务的配置(主要是ssh/rdp/telnet的端口以及录像文件存放路径)
        self._get_core_server_config()

        _db = get_db()
        if not _db.init():
            log.e('can not initialize database interface.\n')
            return 0

        _db.connect()
        while not _db.connected:
            log.w('database not connected, retry after 5 seconds.\n')
            time.sleep(5)
            _db.connect()

        cfg = tp_cfg()

        _db.check_status()
        if _db.need_create or _db.need_upgrade:
            cfg.app_mode = APP_MODE_MAINTENANCE
            tp_cfg().update_sys(None)
        else:
            cfg.app_mode = APP_MODE_NORMAL
            _db.load_system_config()

        try:
            # 将运行时配置发送给核心服务
            req = {'method': 'set_config', 'param': {'noop_timeout': tp_cfg().sys.session.noop_timeout}}
            req_data = json.dumps(req)
            data = urllib.parse.quote(req_data).encode('utf-8')
            req = urllib.request.Request(url=cfg.common.core_server_rpc, data=data)
            rep = urllib.request.urlopen(req, timeout=3)
            body = rep.read().decode()
            x = json.loads(body)
            if 'code' not in x or x['code'] != 0:
                print(x)
                log.e('connect core-server for set runtime-config failed.\n')
            else:
                log.d('set runtime-config for core-server succeeded.\n')
        except:
            log.w('can not connect to core-server to set runtime-config, maybe it not start yet, ignore.\n')

        if not tp_session().init():
            log.e('can not initialize session manager.\n')
            return 0
        if not tp_stats().init():
            log.e('can not initialize system status collector.\n')
            return 0

        settings = {
            #
            'cookie_secret': '8946svdABGD345fg98uhIaefEBePIfegOIakjFH43oETzK',

            'login_url': '/auth/login',

            # 指定静态文件的路径,页面模板中可以用 {{ static_url('css/main.css') }} 的方式调用
            'static_path': cfg.static_path,

            # 指定模板文件的路径
            'template_path': cfg.template_path,

            # 防止跨站伪造请求,参见 http://old.sebug.net/paper/books/tornado/#_7
            'xsrf_cookies': False,

            'autoescape': 'xhtml_escape',

            # 'ui_modules': ui_modules,
            'debug': False,

            # 不开启模板和静态文件的缓存,这样一旦模板文件和静态文件变化,刷新浏览器即可看到更新。
            'compiled_template_cache': False,
            'static_hash_cache': False,
        }

        from app.controller import controllers, fix_controller
        fix_controller()
        _app = tornado.web.Application(controllers, **settings)

        server = tornado.httpserver.HTTPServer(_app, xheaders=True)
        # server = tornado.httpserver.HTTPServer(_app, ssl_options={
        #     "certfile": os.path.join(cfg.data_path, 'cert', "server.pem"),
        #     "keyfile": os.path.join(cfg.data_path, 'cert', "server.key"),
        # })

        try:
            server.listen(cfg.common.port, address=cfg.common.ip)
            if cfg.common.ip == '0.0.0.0':
                log.i('works on [http://127.0.0.1:{}]\n'.format(cfg.common.port))
            else:
                log.i('works on [http://{}:{}]\n'.format(cfg.common.ip, cfg.common.port))
        except:
            log.e('can not listen on port {}:{}, make sure it not been used by another application.\n'.format(cfg.common.ip, cfg.common.port))
            return 0

        # 启动定时任务调度器
        tp_cron().start()

        try:
            tornado.ioloop.IOLoop.instance().start()
        except:
            log.e('\n')

        tp_cron().stop()
        return 0
Ejemplo n.º 14
0
def api_request_session_id(acc_id, protocol_sub_type, client_ip, operator):
    ret = {'code': TPE_OK, 'message': '', 'data': {}}

    conn_info = dict()
    conn_info['_enc'] = 1
    conn_info['host_id'] = 0
    conn_info['client_ip'] = client_ip
    conn_info['user_id'] = 1
    conn_info['user_username'] = operator

    # 直接连接(无需授权,第三方服务操作,已经经过授权检查了)
    err, acc_info = account.get_account_info(acc_id)
    if err != TPE_OK:
        ret['code'] = err
        ret['message'] = '无此远程账号'
        return ret

    host_id = acc_info['host_id']
    acc_info['protocol_flag'] = TP_FLAG_ALL
    acc_info['record_flag'] = TP_FLAG_ALL

    # 获取要远程连接的主机信息(要访问的IP地址,如果是路由模式,则是路由主机的IP+端口)
    err, host_info = host.get_host_info(host_id)
    if err != TPE_OK:
        ret['code'] = err
        ret['message'] = '未找到对应远程主机'
        return ret

    conn_info['host_id'] = host_id
    conn_info['host_ip'] = host_info['ip']
    if len(host_info['router_ip']) > 0:
        conn_info['conn_ip'] = host_info['router_ip']
        conn_info['conn_port'] = host_info['router_port']
    else:
        conn_info['conn_ip'] = host_info['ip']
        conn_info['conn_port'] = acc_info['protocol_port']

    conn_info['acc_id'] = acc_id
    conn_info['acc_username'] = acc_info['username']
    conn_info['username_prompt'] = acc_info['username_prompt']
    conn_info['password_prompt'] = acc_info['password_prompt']
    conn_info['protocol_flag'] = acc_info['protocol_flag']
    conn_info['record_flag'] = acc_info['record_flag']

    conn_info['protocol_type'] = acc_info['protocol_type']
    conn_info['protocol_sub_type'] = protocol_sub_type

    conn_info['auth_type'] = acc_info['auth_type']
    if acc_info['auth_type'] == TP_AUTH_TYPE_PASSWORD:
        conn_info['acc_secret'] = acc_info['password']
    elif acc_info['auth_type'] == TP_AUTH_TYPE_PRIVATE_KEY:
        conn_info['acc_secret'] = acc_info['pri_key']
    else:
        conn_info['acc_secret'] = ''

    with tmp_conn_id_lock:
        global tmp_conn_id_base
        tmp_conn_id_base += 1
        conn_id = tmp_conn_id_base

    # log.v('CONN-INFO:', conn_info)
    tp_session().set('tmp-conn-info-{}'.format(conn_id), conn_info, 10)

    req = {'method': 'request_session', 'param': {'conn_id': conn_id}}
    _yr = core_service_async_post_http(req)
    _code, ret_data = yield _yr
    if _code != TPE_OK:
        ret['code'] = _code
        ret['message'] = '无法连接到核心服务'
        return ret
    if ret_data is None:
        ret['code'] = TPE_FAILED
        ret['message'] = '调用核心服务获取会话ID失败'
        return ret

    if 'sid' not in ret_data:
        ret['code'] = TPE_FAILED
        ret['message'] = '核心服务获取会话ID时返回错误数据'
        return ret

    data = dict()
    data['session_id'] = ret_data['sid']
    data['host_ip'] = host_info['ip']
    data['host_name'] = host_info['name']
    data['protocol_flag'] = acc_info['protocol_flag']

    if conn_info['protocol_type'] == TP_PROTOCOL_TYPE_RDP:
        data['teleport_port'] = tp_cfg().core.rdp.port
    elif conn_info['protocol_type'] == TP_PROTOCOL_TYPE_SSH:
        data['teleport_port'] = tp_cfg().core.ssh.port
    elif conn_info['protocol_type'] == TP_PROTOCOL_TYPE_TELNET:
        data['teleport_port'] = tp_cfg().core.telnet.port

    ret['code'] = TPE_OK
    ret['message'] = ''
    ret['data'] = data
    return ret
Ejemplo n.º 15
0
 def del_session(self, name):
     k = '{}-{}'.format(name, self._s_id)
     return tp_session().set(k, '', -1)
Ejemplo n.º 16
0
 def get_session(self, name, _default=None):
     k = '{}-{}'.format(name, self._s_id)
     return tp_session().get(k, _default)
Ejemplo n.º 17
0
 def set_session(self, name, value, expire=None):
     k = '{}-{}'.format(name, self._s_id)
     tp_session().set(k, value, expire)
Ejemplo n.º 18
0
    def post(self):
        ret = self.check_privilege(TP_PRIVILEGE_SYS_CONFIG)
        if ret != TPE_OK:
            return

        args = self.get_argument('args', None)
        if args is None:
            return self.write_json(TPE_PARAM)
        try:
            args = json.loads(args)
        except:
            return self.write_json(TPE_JSON_FORMAT)

        try:
            processed = False
            if 'smtp' in args:
                processed = True
                _cfg = args['smtp']
                _server = _cfg['server']
                _port = _cfg['port']
                _ssl = _cfg['ssl']
                _sender = _cfg['sender']
                _password = _cfg['password']

                err = system_model.save_config(self, '更新SMTP设置', 'smtp', _cfg)
                if err == TPE_OK:
                    # 同时更新内存缓存
                    tp_cfg().sys.smtp.server = _server
                    tp_cfg().sys.smtp.port = _port
                    tp_cfg().sys.smtp.ssl = _ssl
                    tp_cfg().sys.smtp.sender = _sender
                    # 特殊处理,防止前端拿到密码
                    tp_cfg().sys_smtp_password = _password
                else:
                    return self.write_json(err)

            if 'password' in args:
                processed = True
                _cfg = args['password']
                _allow_reset = _cfg['allow_reset']
                _force_strong = _cfg['force_strong']
                _timeout = _cfg['timeout']
                err = system_model.save_config(self, '更新密码策略设置', 'password',
                                               _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.password.allow_reset = _allow_reset
                    tp_cfg().sys.password.force_strong = _force_strong
                    tp_cfg().sys.password.timeout = _timeout
                else:
                    return self.write_json(err)

            if 'login' in args:
                processed = True
                _cfg = args['login']
                _session_timeout = _cfg['session_timeout']
                _retry = _cfg['retry']
                _lock_timeout = _cfg['lock_timeout']
                _auth = _cfg['auth']
                err = system_model.save_config(self, '更新登录策略设置', 'login', _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.login.session_timeout = _session_timeout
                    tp_cfg().sys.login.retry = _retry
                    tp_cfg().sys.login.lock_timeout = _lock_timeout
                    tp_cfg().sys.login.auth = _auth
                    tp_session().update_default_expire()
                else:
                    return self.write_json(err)

            if 'session' in args:
                processed = True
                _cfg = args['session']
                _noop_timeout = _cfg['noop_timeout']
                _flag_record = _cfg['flag_record']
                _flag_rdp = _cfg['flag_rdp']
                _flag_ssh = _cfg['flag_ssh']
                err = system_model.save_config(self, '更新连接控制设置', 'session',
                                               _cfg)
                if err == TPE_OK:
                    try:
                        req = {
                            'method': 'set_config',
                            'param': {
                                'noop_timeout': _noop_timeout
                            }
                        }
                        _yr = core_service_async_post_http(req)
                        code, ret_data = yield _yr
                        if code != TPE_OK:
                            log.e(
                                'can not set runtime-config to core-server.\n')
                            return self.write_json(code)
                    except:
                        pass

                    tp_cfg().sys.session.noop_timeout = _noop_timeout
                    tp_cfg().sys.session.flag_record = _flag_record
                    tp_cfg().sys.session.flag_rdp = _flag_rdp
                    tp_cfg().sys.session.flag_ssh = _flag_ssh
                else:
                    return self.write_json(err)

            if 'storage' in args:
                processed = True
                _cfg = args['storage']
                _keep_log = _cfg['keep_log']
                _keep_record = _cfg['keep_record']
                _cleanup_hour = _cfg['cleanup_hour']
                _cleanup_minute = _cfg['cleanup_minute']

                if not ((30 <= _keep_log <= 365) or _keep_log == 0):
                    return self.write_json(TPE_PARAM, '系统日志保留时间超出范围!')
                if not ((30 <= _keep_record <= 365) or _keep_record == 0):
                    return self.write_json(TPE_PARAM, '会话录像保留时间超出范围!')

                err = system_model.save_config(self, '更新存储策略设置', 'storage',
                                               _cfg)
                if err == TPE_OK:
                    tp_cfg().sys.storage.keep_log = _keep_log
                    tp_cfg().sys.storage.keep_record = _keep_record
                    tp_cfg().sys.storage.cleanup_hour = _cleanup_hour
                    tp_cfg().sys.storage.cleanup_minute = _cleanup_minute
                else:
                    return self.write_json(err)

            if not processed:
                return self.write_json(TPE_PARAM)

            return self.write_json(TPE_OK)
        except:
            log.e('\n')
            self.write_json(TPE_FAILED)