From 25d562ccf4b2cf0fd0379ecbd0c7df25e24b2498 Mon Sep 17 00:00:00 2001 From: Apex Liu Date: Thu, 1 Nov 2018 03:11:39 +0800 Subject: [PATCH] now can test and save LDAP configurations. --- .../www/teleport/static/js/user/user-list.js | 129 +++++++++--------- server/www/teleport/view/user/user-list.mako | 18 ++- .../www/teleport/webroot/app/base/configs.py | 36 ++++- .../webroot/app/controller/__init__.py | 6 +- .../teleport/webroot/app/controller/system.py | 32 +++++ .../teleport/webroot/app/controller/user.py | 74 +++++----- 6 files changed, 175 insertions(+), 120 deletions(-) diff --git a/server/www/teleport/static/js/user/user-list.js b/server/www/teleport/static/js/user/user-list.js index d7d48b6..c6c8046 100755 --- a/server/www/teleport/static/js/user/user-list.js +++ b/server/www/teleport/static/js/user/user-list.js @@ -28,7 +28,7 @@ $app.on_init = function (cb_stack) { }; cb_stack - // .add($app.test) + .add($app.test) .add($app.create_controls) .add($app.load_role_list); @@ -36,7 +36,7 @@ $app.on_init = function (cb_stack) { }; $app.test = function (cb) { - cb.add($app.dlg_reset_password.show_edit); + cb.add($app.dlg_ldap_config.show); cb.exec(); }; @@ -1225,18 +1225,20 @@ $app.create_dlg_ldap_config = function () { dlg.dom_id = 'dlg-ldap-config'; dlg.mode = 'set'; // edit or set dlg.ldap_config = { - host: '', + server: '', port: '', domain: '', + admin: '', + password: '', base_dn: '', filter: '', attr_map: '' }; - dlg.ldap_config_password = ''; + // {"server":"192.168.0.101","port":3892,"domain":"apexnas.com","admin":"cn=admin,dc=apexnas,dc=com","password":"Abcd1234","base_dn":"ou=people,dc=apexnas,dc=com","filter":"(&(objectClass=person))","attr_map":"tp.username = uid\ntp.surname = cn111\ntp.email = mail"} dlg.dom = { dialog: $('#' + dlg.dom_id), - host: $('#edit-ldap-host'), + server: $('#edit-ldap-server'), port: $('#edit-ldap-port'), domain: $('#edit-ldap-domain'), admin: $('#edit-ldap-admin'), @@ -1273,41 +1275,36 @@ $app.create_dlg_ldap_config = function () { dlg.dom.btn_switch_password_icon.removeClass('fa-eye-slash').addClass('fa-eye') } }); - // - // if (!$app.options.sys_smtp) - // dlg.dom.msg_cannot_send_email.text('未配置邮件发送服务'); - dlg.dom.dialog.modal({backdrop: 'static'}); cb_stack.exec(); }; - dlg.init_fields = function (ldap_config) { - // dlg.field_id = user.id; - // dlg.field_email = user.email; - // dlg.dom.dlg_title.html('密码重置:' + user.surname); - // - // dlg.dom.password.val(''); - // - // if (!$app.options.sys_smtp || user.email.length === 0) { - // dlg.dom.email.text(''); - // dlg.dom.can_send_email.hide(); - // dlg.dom.cannot_send_email.show(); - // } else { - // dlg.dom.email.text(user.email); - // dlg.dom.can_send_email.show(); - // dlg.dom.cannot_send_email.hide(); - // } + dlg.init_fields = function () { + if(0 === $app.options.sys_cfg.ldap.server.length) { + dlg.mode = 'set'; + } else { + dlg.ldap_config = $app.options.sys_cfg.ldap; + + dlg.mode = 'edit'; + // dlg.dom.password.val(); + dlg.dom.server.val(dlg.ldap_config.server); + dlg.dom.port.val(dlg.ldap_config.port); + dlg.dom.domain.val(dlg.ldap_config.domain); + dlg.dom.admin.val(dlg.ldap_config.admin); + dlg.dom.base_dn.val(dlg.ldap_config.base_dn); + dlg.dom.filter.val(dlg.ldap_config.filter); + dlg.dom.attr_map.text(dlg.ldap_config.attr_map); + } }; dlg.show = function () { - // var user = $app.table_users.get_row(row_id); - // dlg.init_fields(user); + dlg.init_fields(); dlg.dom.dialog.modal({backdrop: 'static'}); }; dlg.check_fields = function () { - dlg.ldap_config_password = dlg.dom.password.val(); - dlg.ldap_config.host = dlg.dom.host.val(); + dlg.ldap_config.password = dlg.dom.password.val(); + dlg.ldap_config.server = dlg.dom.server.val(); dlg.ldap_config.domain = dlg.dom.domain.val(); dlg.ldap_config.port = parseInt(dlg.dom.port.val()); dlg.ldap_config.admin = dlg.dom.admin.val(); @@ -1315,8 +1312,8 @@ $app.create_dlg_ldap_config = function () { dlg.ldap_config.filter = dlg.dom.filter.val(); dlg.ldap_config.attr_map = dlg.dom.attr_map.val(); - if (!tp_is_host(dlg.ldap_config.host)) { - dlg.dom.host.focus(); + if (!tp_is_host(dlg.ldap_config.server)) { + dlg.dom.server.focus(); $tp.notify_error('请填写LDAP主机地址!'); return false; } @@ -1342,11 +1339,15 @@ $app.create_dlg_ldap_config = function () { $tp.notify_error('请填写LDAP的管理员用户名!'); return false; } - if (tp_is_empty_str(dlg.ldap_config_password)) { - dlg.dom.password.focus(); - $tp.notify_error('请填写LDAP的管理员密码!'); - return false; + + if(dlg.mode === 'set') { + if (tp_is_empty_str(dlg.ldap_config.password)) { + dlg.dom.password.focus(); + $tp.notify_error('请填写LDAP的管理员密码!'); + return false; + } } + if (tp_is_empty_str(dlg.ldap_config.base_dn)) { dlg.dom.base_dn.focus(); $tp.notify_error('请填写LDAP的用户基准DN!'); @@ -1369,13 +1370,12 @@ $app.create_dlg_ldap_config = function () { dlg.do_list_attr = function () { if (!dlg.check_fields()) return; - dlg.dom.btn_test.attr('disabled', 'disabled'); + dlg.dom.btn_list_attr.attr('disabled', 'disabled'); $tp.ajax_post_json('/user/do-ldap-config-list-attr', { - c: dlg.ldap_config, - p: dlg.ldap_config_password + ldap: dlg.ldap_config }, function (ret) { - dlg.dom.btn_test.removeAttr('disabled'); + dlg.dom.btn_list_attr.removeAttr('disabled'); if (ret.code === TPE_OK) { $tp.notify_success('列举LDAP用户属性成功!'); console.log(ret.data); @@ -1385,7 +1385,7 @@ $app.create_dlg_ldap_config = function () { } }, function () { - dlg.dom.btn_test.removeAttr('disabled'); + dlg.dom.btn_list_attr.removeAttr('disabled'); $tp.notify_error('网络故障,列举LDAP用户属性失败!'); }, 15000 @@ -1397,8 +1397,7 @@ $app.create_dlg_ldap_config = function () { return; dlg.dom.btn_test.attr('disabled', 'disabled'); $tp.ajax_post_json('/user/do-ldap-config-test', { - c: dlg.ldap_config, - p: dlg.ldap_config_password + ldap: dlg.ldap_config }, function (ret) { dlg.dom.btn_test.removeAttr('disabled'); @@ -1416,37 +1415,31 @@ $app.create_dlg_ldap_config = function () { }, 15000 ); - }; dlg.do_save = function () { if (!dlg.check_fields()) return; - // dlg.field_password = dlg.dom.password.val(); - // if (dlg.field_password.length === 0) { - // dlg.dom.field_password.focus(); - // $tp.notify_error('请先填写用户的新密码!'); - // return; - // } - // - // $tp.ajax_post_json('/user/do-reset-password', { - // mode: 2, - // id: dlg.field_id, - // password: dlg.field_password - // }, - // function (ret) { - // if (ret.code === TPE_OK) { - // $tp.notify_success('用户密码重置成功!'); - // dlg.dom.dialog.modal('hide'); - // } else { - // $tp.notify_error('用户密码重置失败:' + tp_error_msg(ret.code, ret.message)); - // } - // }, - // function () { - // $tp.notify_error('网络故障,用户密码重置失败!'); - // } - // ); - // + dlg.dom.btn_save.attr('disabled', 'disabled'); + $tp.ajax_post_json('/system/save-cfg', { + ldap: dlg.ldap_config + }, + function (ret) { + dlg.dom.btn_save.removeAttr('disabled'); + if (ret.code === TPE_OK) { + $app.options.sys_cfg.ldap = dlg.ldap_config; + $tp.notify_success('保存LDAP设置成功!'); + } else { + $tp.notify_error('保存LDAP设置失败:' + tp_error_msg(ret.code, ret.message)); + } + }, + function () { + dlg.dom.btn_save.removeAttr('disabled'); + $tp.notify_error('网络故障,保存LDAP设置失败!'); + }, + 15000 + ); + }; return dlg; diff --git a/server/www/teleport/view/user/user-list.mako b/server/www/teleport/view/user/user-list.mako index 6269b5f..f391a1a 100644 --- a/server/www/teleport/view/user/user-list.mako +++ b/server/www/teleport/view/user/user-list.mako @@ -389,23 +389,23 @@
- +
- +
- +
- +
LDAP的账号使用 用户名@域 来登录teleport。
@@ -415,7 +415,7 @@
- +
LDAP服务的管理员账号,用于列举用户、同步账号。
@@ -426,7 +426,7 @@
- +
@@ -444,7 +444,7 @@
- +
限制用户DN的范围,例如 ou=dev,ou=company,ou=com。用户的完整DN为 cn=用户登录名,用户基准DN
@@ -460,9 +460,7 @@
- +
将LDAP的属性映射到 teleport 的用户属性,例如 LDAP中的用户属性 sAMAccountName 映射为teleport的登录账号。如果不清楚此LDAP服务的用户属性,可使用下方的“列举属性”按钮进行查询。
diff --git a/server/www/teleport/webroot/app/base/configs.py b/server/www/teleport/webroot/app/base/configs.py index b3df8a6..8410015 100644 --- a/server/www/teleport/webroot/app/base/configs.py +++ b/server/www/teleport/webroot/app/base/configs.py @@ -146,7 +146,8 @@ class BaseAppConfig(dict): for k in sections[sec_name]: _k = k.replace('-', '_') have_comment = False - if sec_name in self['_cfg_default'] and _k in self['_cfg_default'][sec_name] and 'comment' in self['_cfg_default'][sec_name][_k]: + if sec_name in self['_cfg_default'] and _k in self['_cfg_default'][sec_name] and 'comment' in \ + self['_cfg_default'][sec_name][_k]: comments = self['_cfg_default'][sec_name][_k]['comment'] if comments is not None: comments = self['_cfg_default'][sec_name][_k]['comment'].split('\n') @@ -266,6 +267,7 @@ class AppConfig(BaseAppConfig): self.sys = AttrDict() self.sys.loaded = False self.sys_smtp_password = '' # 密码单独处理,避免无意中传递给前端页面了 + self.sys_ldap_password = '' def _on_init(self): self.set_default('common::ip', '0.0.0.0', 'ip=0.0.0.0') @@ -313,7 +315,8 @@ class AppConfig(BaseAppConfig): def _on_get_save_info(self): return [ {'common': ['ip', 'port', 'log-file', 'log-level', 'debug-mode', 'core-server-rpc']}, - {'database': ['type', 'sqlite-file', 'mysql-host', 'mysql-port', 'mysql-db', 'mysql-prefix', 'mysql-user', 'mysql-password']} + {'database': ['type', 'sqlite-file', 'mysql-host', 'mysql-port', 'mysql-db', 'mysql-prefix', 'mysql-user', + 'mysql-password']} ] def _on_load(self, cfg_parser): @@ -555,6 +558,35 @@ class AppConfig(BaseAppConfig): if not self.sys.storage.is_exists('cleanup_minute'): self.sys.storage.cleanup_minute = 30 + # ===================================== + # LDAP相关 + # ===================================== + self.sys_ldap_password = '' + try: + _ldap = json.loads(conf_data['ldap']) + except: + log.w('ldap config not set or invalid, use default.\n') + _ldap = {} + + self.sys.ldap = tp_convert_to_attr_dict(_ldap) + if not self.sys.ldap.is_exists('server'): + self.sys.ldap.server = '' + if not self.sys.ldap.is_exists('port'): + self.sys.ldap.port = 389 + if not self.sys.ldap.is_exists('domain'): + self.sys.ldap.domain = '' + if not self.sys.ldap.is_exists('admin'): + self.sys.ldap.admin = '' + if not self.sys.ldap.is_exists('base_dn'): + self.sys.ldap.base_dn = '' + if not self.sys.ldap.is_exists('filter'): + self.sys.ldap.filter = '' + if not self.sys.ldap.is_exists('attr_map'): + self.sys.ldap.attr_map = '' + if self.sys.ldap.is_exists('password'): + self.sys_ldap_password = self.sys.ldap.password + self.sys.ldap.password = '********' + self.sys.loaded = True return True diff --git a/server/www/teleport/webroot/app/controller/__init__.py b/server/www/teleport/webroot/app/controller/__init__.py index 8114ac3..edb2ba8 100755 --- a/server/www/teleport/webroot/app/controller/__init__.py +++ b/server/www/teleport/webroot/app/controller/__init__.py @@ -80,10 +80,12 @@ controllers = [ (r'/user/do-bind-oath', user.DoBindOathHandler), # - [json] 取消绑定身份认证器 (r'/user/do-unbind-oath', user.DoUnBindOathHandler), - # - [json] 测试LDAP的配置 - (r'/user/do-ldap-config-test', user.DoLdapConfigTestHandler), # - [json] 列出LDAP服务器的用户的属性,便于管理员做属性映射 (r'/user/do-ldap-config-list-attr', user.DoLdapListUserAttrHandler), + # - [json] 测试LDAP的配置 + (r'/user/do-ldap-config-test', user.DoLdapConfigTestHandler), + # # - [json] 保存LDAP服务器配置项 + # (r'/user/do-ldap-config-save', user.DoLdapConfigSaveHandler), # # - 用户组管理页面 (r'/user/group', user.GroupListHandler), diff --git a/server/www/teleport/webroot/app/controller/system.py b/server/www/teleport/webroot/app/controller/system.py index 5c1523f..86661be 100644 --- a/server/www/teleport/webroot/app/controller/system.py +++ b/server/www/teleport/webroot/app/controller/system.py @@ -241,6 +241,9 @@ class DoSaveCfgHandler(TPBaseJsonHandler): _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: # 同时更新内存缓存 @@ -332,6 +335,35 @@ class DoSaveCfgHandler(TPBaseJsonHandler): 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_map = _cfg['attr_map'] + + # TODO: encrypt the password before save by core-service. + # TODO: if not send password, use pre-saved password. + + 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_map = _attr_map + # 特殊处理,防止前端拿到密码 + tp_cfg().sys_ldap_password = _password + else: + return self.write_json(err) + if not processed: return self.write_json(TPE_PARAM) diff --git a/server/www/teleport/webroot/app/controller/user.py b/server/www/teleport/webroot/app/controller/user.py index 10d9624..1656dbd 100755 --- a/server/www/teleport/webroot/app/controller/user.py +++ b/server/www/teleport/webroot/app/controller/user.py @@ -907,40 +907,6 @@ class DoGetRoleListHandler(TPBaseJsonHandler): self.write_json(TPE_OK, data=role_list) -class DoLdapConfigTestHandler(TPBaseJsonHandler): - def post(self): - ret = self.check_privilege(TP_PRIVILEGE_USER_CREATE) - 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: - cfg = args['c'] - cfg['port'] = int(cfg['port']) - password = args['p'] - except: - return self.write_json(TPE_PARAM) - - try: - # ldap = Ldap(cfg['host'], cfg['port'], cfg['base_dn'], cfg['domain']) - ldap = Ldap(cfg['host'], cfg['port'], cfg['base_dn']) - ret, data, err_msg = ldap.list_users(cfg['admin'], password, cfg['filter'], cfg['attr_map'], size_limit=10) - if ret != TPE_OK: - return self.write_json(ret, message=err_msg) - else: - return self.write_json(ret, data=data) - except: - log.e('') - return self.write_json(TPE_PARAM) - - class DoLdapListUserAttrHandler(TPBaseJsonHandler): def post(self): ret = self.check_privilege(TP_PRIVILEGE_USER_CREATE) @@ -956,15 +922,47 @@ class DoLdapListUserAttrHandler(TPBaseJsonHandler): return self.write_json(TPE_JSON_FORMAT) try: - cfg = args['c'] + cfg = args['ldap'] cfg['port'] = int(cfg['port']) - password = args['p'] except: return self.write_json(TPE_PARAM) try: - ldap = Ldap(cfg['host'], cfg['port'], cfg['base_dn']) - ret, data, err_msg = ldap.get_all_attr(cfg['admin'], password, cfg['filter']) + ldap = Ldap(cfg['server'], cfg['port'], cfg['base_dn']) + ret, data, err_msg = ldap.get_all_attr(cfg['admin'], cfg['password'], cfg['filter']) + if ret != TPE_OK: + return self.write_json(ret, message=err_msg) + else: + return self.write_json(ret, data=data) + except: + log.e('') + return self.write_json(TPE_PARAM) + + +class DoLdapConfigTestHandler(TPBaseJsonHandler): + def post(self): + ret = self.check_privilege(TP_PRIVILEGE_USER_CREATE) + 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: + cfg = args['ldap'] + cfg['port'] = int(cfg['port']) + except: + return self.write_json(TPE_PARAM) + + try: + # ldap = Ldap(cfg['host'], cfg['port'], cfg['base_dn'], cfg['domain']) + ldap = Ldap(cfg['server'], cfg['port'], cfg['base_dn']) + ret, data, err_msg = ldap.list_users(cfg['admin'], cfg['password'], cfg['filter'], cfg['attr_map'], size_limit=10) if ret != TPE_OK: return self.write_json(ret, message=err_msg) else: