Open wklken opened 2 years ago
用户管理版本<=2.3.3
)ldap服务端: OpenLDAP, 启动时mode=ipv4_only (-4 Listen on IPv4 addresses only
)
报错
Traceback (most recent call last):
File "/app/bkuser_core/categories/plugins/ldap/client.py", line 71, in initialize
return Connection(**connection_params)
File "/usr/local/lib/python3.6/site-packages/ldap3/core/connection.py", line 326, in __init__
self.do_auto_bind()
File "/usr/local/lib/python3.6/site-packages/ldap3/core/connection.py", line 341, in do_auto_bind
self.open(read_server_info=False)
File "/usr/local/lib/python3.6/site-packages/ldap3/strategy/sync.py", line 56, in open
BaseStrategy.open(self, reset_usage, read_server_info)
File "/usr/local/lib/python3.6/site-packages/ldap3/strategy/base.py", line 150, in open
raise LDAPSocketOpenError('invalid server address')
ldap3.core.exceptions.LDAPSocketOpenError: invalid server address
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/bkuser_core/categories/views.py", line 197, in test_connection
syncer_cls(instance.id).fetcher.client.initialize(**serializer.validated_data)
File "<string>", line 6, in __init__
File "/app/bkuser_core/categories/plugins/ldap/syncer.py", line 159, in __post_init__
self.fetcher: LDAPFetcher = self.get_fetcher()
File "/app/bkuser_core/categories/plugins/base.py", line 230, in get_fetcher
return self.fetcher_cls(self.category_id, self.config_loader)
File "<string>", line 4, in __init__
File "/app/bkuser_core/categories/plugins/ldap/syncer.py", line 40, in __post_init__
self.client = LDAPClient(self.config_loader)
File "<string>", line 3, in __init__
File "/app/bkuser_core/categories/plugins/ldap/client.py", line 38, in __post_init__
use_ssl=bool(self.config_provider.get("ssl_encryption") == "SSL"),
File "/app/bkuser_core/categories/plugins/ldap/client.py", line 79, in initialize
raise local_exceptions.LdapCannotBeInitialized
bkuser_core.categories.plugins.ldap.exceptions.LdapCannotBeInitialized
处理:
进入用户管理容器或虚拟环境, 升级ldap3
到 2.7
解决; 点击连接测试, 测试通过
pip install ldap3==2.7
相关issue:
TODO
使用openldap账户@登录域 的用户名和密码登不上环境; 登录提示: 账户名和密码不匹配
报错日志:
INFO [2022-04-11 12:08:04] bkuser.categories.vendors.ldap.client(ln:74): going to search (objectClass=inetOrgPerson) from ou=rd_xxxn,ou=rd,ou=People,dc=test,dc=com
ERROR [2022-04-11 12:08:04] bkuser.profiles.views(ln:529): check profile<bkdevops> failed
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser/profiles/views.py", line 527, in login
File "/data/bkce/usermgr/api/bkuser/categories/vendors/ldap/login.py", line 38, in check
File "/data/bkce/usermgr/api/bkuser/categories/vendors/ldap/client.py", line 94, in check
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/ldap3/core/connection.py", line 326, in __init__
self.do_auto_bind()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/ldap3/core/connection.py", line 354, in do_auto_bind
raise LDAPBindError(self.last_error)
ldap3.core.exceptions.LDAPBindError: automatic bind not successful - invalidCredentials
页面报错提示:
LDAP服务器连接失败 (ldap3.core.exceptions.LDAPBindError: automatic bind not successful - invalidCredentials)
原因: 配置的 LDAP 管理密码有误
相关issue
解决方案:在LDAP字段配置 -> 中文名处设置
相关issue:
ldap 地址规则:
ldap://x.x.x.x:389
(注意这里端口需要根据自己环境服务提供端口修改)ldaps://x.x.x.x:636
(注意这里端口需要根据自己环境服务提供端口修改)
SSL 加密方式
需要下拉选择SSL
配置错误可能的报错:
相关issue:
新建 ldap 同步目录的时候, 会有一个域
(domain), 例如abc
, domain是目录创建时指定的唯一标识
登录目前的交互是需要, 用户名输入框需要用户主动填写域
, 否则登录校验走默认目录
格式: {identity}@域
, 邮箱除外(邮箱相当于自带了域, 即, 想支持邮箱登录, 邮箱后缀需要与ldap目录的域
一致)
所以登录时, ldap 同步过来的用户, 用户名需要填写用户名@abc
/手机号@abc
/邮箱
相关issue:
Q: 用户集成了Windows AD,但是修改的密码无法同步到AD域里,请问可以实现密码同步更能嘛? A: 我们目前不会向 AD 做任何的写操作,建议直接在 AD 中修改密码
相关issue: #313
Q: 对接公司内部的单点系统之后,所有用户登录都是普通用户,admin不能登录了 A: 需要提前进入用户管理后台 Python 环境(具体步骤依赖部署方式)
from bkuser_core.profiles.models import Profile
from bkuser_core.categories.models import ProfileCategory
p = ProfileCategory.objects.get(id=${期望目录id})
Profile.objects.create(username="admin", domain=p.domain, category_id=p.id)
相关issue: #314
ldap 地址规则:
ldap3.core.exceptions.LDAPSocketOpenError
应该如何测试配置地址是否正确需要在用户管理(后台api)部署的机器/容器上验证:
nc
确定
LDAP
389, 命令: nc <ldapserverip> 389 -v -w 60
LDAPs
636, 命令: nc <ldapserverip> 636 -v -w 60
telnet
确定
telnet <ldap-server-fqdn> <ldap-port>
curl
确定: curl -v IP:389
需要补充:
https://bk.tencent.com/s-mart/community/question/1901
KeyError: 'entrydn'
报错详情
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser_core/profiles/views.py", line 620, in login
login_class().check(profile, password)
File "/data/bkce/usermgr/api/bkuser_core/categories/plugins/ldap/login.py", line 45, in check
target_dn = self.fetch_dn(user)
File "/data/bkce/usermgr/api/bkuser_core/categories/plugins/ldap/login.py", line 26, in fetch_dn
return force_str(user_info["raw_attributes"]["entryDN"][0])
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/ldap3/utils/ciDict.py", line 68, in __getitem__
return self._store[self._case_insensitive_keymap[self._ci_key(key)]]
KeyError: 'entrydn'
ERROR [2021-10-28 14:44:25] bkuser_core.common.exception_handler(ln:81): request apiServer failed
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser_core/profiles/views.py", line 620, in login
login_class().check(profile, password)
File "/data/bkce/usermgr/api/bkuser_core/categories/plugins/ldap/login.py", line 45, in check
target_dn = self.fetch_dn(user)
File "/data/bkce/usermgr/api/bkuser_core/categories/plugins/ldap/login.py", line 26, in fetch_dn
return force_str(user_info["raw_attributes"]["entryDN"][0])
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/ldap3/utils/ciDict.py", line 68, in __getitem__
return self._store[self._case_insensitive_keymap[self._ci_key(key)]]
KeyError: 'entrydn'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/rest_framework/views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "/data/bkce/usermgr/api/bkuser_core/profiles/views.py", line 635, in login
raise error_codes.PASSWORD_ERROR
bkuser_core.common.error_codes.CoreAPIError: CoreAPIError 400-PASSWORD_ERROR```
原因: 从 LDAP 服务器中读取出的用户属性中没有 entryDN;
处理: 需要确认一下你们使用的是 OpenLDAP 还是 Microsoft Active Directory, 二者的配置会有些差异 最终确认, 服务器是 AD, 但在用户管理配置成了 LDAP 导致的; 使用 AD 接入, 调试成功
相关issue:
问题: 用户的openldap服务没有开启memberOf模块,用户管理的ldap同步会失败,提示没有memberOf属性。 并非所有用户需要开启memberOf模块,即使后续开启memberOf模块,对openldap原先的存量用户也不起作用,造成一些没有memberOf的的openldap用户无法使用用户管理ldap同步功能
报错详情:
Traceback (most recent call last):
...
raise LDAPAttributeError('invalid attribute type ' + attribute_name_to_check)
ldap3.core.exceptions.LDAPAttributeError: invalid attribute type memberOf
先确认用户管理ldap配置是否正确
如果升级到了最新版,这里用户组关联字段是可以不填写的,留空即不同步用户组数据
解决问题的思路:
memberOf
,并且可以刷新数据的情况,可以参考 https://blog.adimian.com/2014/10/15/how-to-enable-memberof-using-openldap/ 操作 ldap 服务器另外, 如果使用的 LDAP 是由类似 OpenDJ
这样的服务提供
那么你需要手动修改用户组默认属性配置,由 memberOf
修改为 isMemberOf
进入 Api 模块的 Python Shell 环境:
from bkuser_core.user_settings.models import Setting
# 填写相关联的目录 ID
s = Setting.objects.get(category_id=${category_id}, meta__key="user_member_of")
s.value = "isMemberOf"
s.save()
相关issue:
username<小明> does not meet format
报错详情:
[2022-05-12 16:20:24,212: INFO/ForkPoolWorker-9] 同步总耗时: 2.444955825805664s, 消耗总CPU时间: 0.175728s.
[2022-05-12 16:29:04,212: WARNING/ForkPoolWorker-11] username<小明> does not meet format
username does not meet format
displayName
)解决: 改成uid
后同步成功
username 命名规范: 由1-32位字母、数字、下划线(_)、点(.)、减号(-)字符组成,以字母或数字开头
不能包含空格
/中文
/特殊字符
等
报错详情:
bkuser.categories.exceptions.FetchDataFromRemoteFailed: 无法获取用户数据, 请检查配置
mail
. 具体可以参考 用户管理LDAP,AD同步FQA version < 2.2.6-b3
version > 2.2.6-b3
可以, 使用多个目录, 每个目录配置不同域, 使用ldap分别同步即可
登录时, 用户名为 username@域
相关issue: https://bk.tencent.com/s-mart/community/question/2049?type=answer
报错详情:
pymysql.err.IntegrityError: (1062, "Duplicate entry 'xxxxx' for key 'code'")
dn
冲突了相关issue:
报错日志中包含: Department bulk_create failed
关键字
由于 2.5 及之前的版本, 目录的删除是软删除
, 导致用户可能新建一个测试目录, 配置ldap测试同步, 之后删除这个目录, 新建一个正式的目录, 配置同一个ldap源
注意, 软删除之后目前在产品页面是看不到的, 无法恢复或者硬删除, #441 (后续版本会解决)
并且, 2.5 及之前的版本, 存在一个bug #714 (后续版本会解决), 使用的部门full_name作为的code数据库唯一约束(例如: 总公司/研发部),
这样就会导致出现这个冲突的原因有很多:
总公司/研发部
, 概率比较低)注意, 如果报 1406, Data too long for column 'code'
, 可以尝试把部门表的code先改长再同步试试
alter table departments_department modify `code` varchar(256) DEFAULT NULL
原因 1
导致的, 需要从ldap服务数据本身解决, 源头就应该不能有同一个节点下有两个同名的部门原因 2
导致的
原因 3
导致的, 看看是否能避免从两个ldap同步数据到同一个用户管理; 如果确实有这种需求, 需要等待用户管理后续版本修正 #714 修复: 使用version >=2.2.4
进行修复
相关issue:
待确认:
更改1000人限制:修改自己的MAD属性maxPageSize到5000 LDAP Query returns only 1000 entries, and LDAP Sync return error Sizelimit exceeded
记得要将maxPageSize设置到大于实际ad人数,也就是说要拉取全部人才能正常登录
相关issue:
不能, 当前邮箱是必填字段; (涉及到登录/消息通知等场景)
相关issue:
域
的新目录 (version==2.2.4)用户管理2.2.4已知bug,下个版本修复
临时处理:
mysql --login-path=mysql-default
select * from bk_user.categories_profilecategory\G #找到恢复目录的id
update bk_user.categories_profilecategory set enabled=1 where id=想要恢复的id;
处理方案: 升级到version > 2.2.4
相关issue:
解决方案:
mysql --login-path=mysql-default
select * from bk_user.profiles_profile\G #找到恢复用户的id
update bk_user.profiles_profile set enabled=1, status='NORMAL' where id=想要恢复的id;
然后在用户管理--选择目录--从其他组织目录拉取--选择该用户--提交
注意, 恢复后, 必须确认用户已经存在于某个部门下(否则鉴权时接口可能会报错); 可以在相应部门目录下, 通过添加用户, 建立用户-部门
的关系
相关issue:
账户或者密码错误,请重新输入
如果确认, 用户名是正确的, 且有加域
(格式: username@domain
, 且密码也是正确的;
由于安全因素, 登录校验时, 用户如果不存在/多个用户/用户被删除/用户处于冻结状态等等, 统一会返回账户或者密码错误,请重新输入
具体原因查看:
admin
登入用户管理, 在审计-登录审计
, 可以看到具体用户登录失败原因报错详情:
ldap3.core.exceptions.LDAPAttributeError: invalid attribute type memberOf
相关issue: https://bk.tencent.com/s-mart/community/question/2775?type=answer
原因: 权限中心每天定时在临时从用户管理同步组织架构, 所以存在时间差; 可以到权限中心以admin的身份, 点击主动同步
相关issue:
用户管理内置字段无法满足同步需求怎么处理?### 1、在设置-->用户字段设置 中添加所需的字段。 2、在LDAP/MAD同步的字段配置-->自定义字段 选择需要同步的字段信息。可对添加的字段做增减。
需要同时查看应用日志及celery日志(最终执行同步在celery中执行的)
二进制:
容器化7.0
注意, 仅用于排查问题时的查询, 不要修改任何未经过确认的字段值, 不要删除任何数据;(以上都可能导致同步失败等各种奇奇怪怪的问题, 并且可能造成数据丢失无法恢复)
报错关键字:
Duplicate entry '' for key 'code'
报错原因:
注意: 只要code不变, 那么在权限中心等, 是同一个用户;
code的生成规则:
sha256(category_id + ldap_object[dn])
所以, 如果服务端dn重复, 会导致同步失败; 如果往目录 1 配置同步过一次, 后来改了配置又同步, 存在重复dn也会冲突;
查看目录列表 (注意: status=normal, enabled=1
才会在页面上展示)
select * from categories_profilecategory;
查看目录的配置
select b.key, a.value, a.enabled, a.category_id, a.meta_id from user_settings_setting a, user_settings_settingmeta b where a.meta_id=b.id
and a.category_id=123;
查看某个用户 (注意查看status
/staff_status
/enabled
几个字段)
# code / username / display_name
select * from profiles_profile where code='xxxxxx';
select * from profiles_profile where username='xxxxx';
select * from profiles_profile where category_id=2 limit 10;
查看某个部门的信息
select * from departments_department where name='DEPT_NAME ';
select * from departments_department where category_id=2 limit 10;
查询部门-用户关系表
select * from departments_department_profiles where category_id=2;
# 部门下的所有用户
select * from departments_department_profiles where department_id=123;
# 用户的所有部门
select * from departments_department_profiles where profile_id=123;
处理:
Traceback (most recent call last):
File "/app/bkuser_core/categories/plugins/ldap/client.py", line 71, in initialize
return Connection(**connection_params)
File "/usr/local/lib/python3.6/site-packages/ldap3/core/connection.py", line 326, in __init__
self.do_auto_bind()
File "/usr/local/lib/python3.6/site-packages/ldap3/core/connection.py", line 341, in do_auto_bind
self.open(read_server_info=False)
File "/usr/local/lib/python3.6/site-packages/ldap3/strategy/sync.py", line 56, in open
BaseStrategy.open(self, reset_usage, read_server_info)
File "/usr/local/lib/python3.6/site-packages/ldap3/strategy/base.py", line 150, in open
raise LDAPSocketOpenError('invalid server address')
ldap3.core.exceptions.LDAPSocketOpenError: invalid server address
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/bkuser_core/categories/views.py", line 197, in test_connection
syncer_cls(instance.id).fetcher.client.initialize(**serializer.validated_data)
File "<string>", line 6, in __init__
File "/app/bkuser_core/categories/plugins/ldap/syncer.py", line 159, in __post_init__
self.fetcher: LDAPFetcher = self.get_fetcher()
File "/app/bkuser_core/categories/plugins/base.py", line 230, in get_fetcher
return self.fetcher_cls(self.category_id, self.config_loader)
File "<string>", line 4, in __init__
File "/app/bkuser_core/categories/plugins/ldap/syncer.py", line 40, in __post_init__
self.client = LDAPClient(self.config_loader)
File "<string>", line 3, in __init__
File "/app/bkuser_core/categories/plugins/ldap/client.py", line 38, in __post_init__
use_ssl=bool(self.config_provider.get("ssl_encryption") == "SSL"),
File "/app/bkuser_core/categories/plugins/ldap/client.py", line 79, in initialize
raise local_exceptions.LdapCannotBeInitialized
bkuser_core.categories.plugins.ldap.exceptions.LdapCannotBeInitialized
ldap3从 2.6.1, 升级到 2.7 之后解决;
问题: 同步时, 入数据库pymysql报错, 无法保存部门或用户
报错详情:
pymyagl.err.InternalError:(1271, "Illegal mix of collations for operation 'case')
原因:
COLLATE
不是 utf8_general_ci
(show variables like "collation_database";
/ show table status;
)相关issue:
ldap3.core.exceptions.LDAPSessionTerminatedByServerError: session terminated by server
ldap3.core.exceptions.LDAPSessionTerminatedByServerError: session terminated by server
issue: cannatag/ldap3#513
这个报错是使用开源包 ldap3 调用请求 ldap服务器报的, 非业务代码逻辑问题
; 大概率是ldap服务/网络导致的, 也可能是配置的调用参数未被授权;
按照搜索结果逐一排查, 例如这种: https://github.com/cannatag/ldap3/issues/513#issuecomment-387873117
dc=a,dc=b,dc=local
|- ou=Group
|- ou=SubGroup
|- uid=abcdefg
这种情况下, 配置拉取节点 ou=Gorup,dc=a,dc=b,dc=local
会发现, uid对应的用户, 绑在 Group
下, 而不是SubGroup
这个问题尚未解决, 暂时无法支持到uid=abcdefg
的这种ldap数据
什么情况能清理:
Duplicate entry 'xxxxx' for key 'code'
清理掉意味着废弃掉已有组织架构及用户, 如果权限中心已经同步组织架构过去了, 那么不能清理 (要么用户管理+权限中心都重置) => 如果清理, 权限中心下次同步将会出现数据错乱/权限错乱, 无法恢复
select * from categories_profilecategory;
# 获取 category的id, 替换下面sql的x
# 删目录下用户
delete from profiles_profile where category_id=x;
# 删部门
UPDATE departments_department SET parent_id = NULL WHERE parent_id IS NOT NULL AND category_id=x;
delete from departments_department where category_id=x;
# 删部门-用户关系表
delete from departments_department_profiles where department_id not in (select id from departments_department);
# 删用户-leader关系表
delete from profiles_profile_leader where from_profile_id not in (select id from profiles_profile);
openLDAP的sizelimit默认值为500,会导致只能同步500账号到bk-user, 超限后新用户无法同步。 openLDAP限制参考:https://www.openldap.org/doc/admin24/limits.html
临时解决办法: 修改openLDAP默认值,参考如下:
更优解决办法: 建议bk-user优化同步逻辑,按需增量同步(比如用户第一次登录时,触发该账号和上下级关联账号同步),避免全量同步LDAP用户和组织架构到bk-user。
cat > sizelimit.ldif
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f sizelimit.ldif modifying entry "cn=config"
相关issue:
# 查看目录所有配置及其更新时间
select b.key, a.value, a.enabled, a.category_id, a.meta_id, a.create_time, a.update_time from user_settings_setting a, user_settings_settingmeta b where a.meta_id=b.id
and a.category_id=4;
# 查用户/部门数据(査几条看看, 必要的话order by id desc看最新的)
select * from profiles_profile where category_id=4 limit 10;
select * from departments_department where category_id=4 limit 10;
# 查询某个category中用户/部门启用的数据
select enabled, count(*) from profile_profiles where category_id=4 group by enabled;
select enabled, count(*) from departments_department where category_id=4 group by enabled;
# 査部门-用户关系表中的数据
select count(*) from departments_department_profiles where department_id in (select id from departments_department where enabeld=1 and category_id=4);
select count(*) from departments_department_profiles where department_id in (select id from departments_department where enabeld=0 and category_id=4);
code
冲突注意第三步恢复部门及用户, 可能恢复后有脏数据(之前被软删除的也被恢复了), 因为此时无法识别哪些是之前删除的, 哪些是删目录的时候删除的
删目录删除的=>其update_time应该是一致的或接近的, 可以多加一个条件update_time>xxxx
防止恢复了脏数据
注意: 如果不确定, 就不要操作; 如果能回滚db, 会是一个更好的选择
恢复sql
select * from categories_profilecategory;
# 找到被误删的记录 获取 category的id, 替换下面sql的x
# 1. 恢复目录
update categories_profilecategory set enabled=1, status="normal" where id=x;
# 2. 恢复配置
update user_settings_setting set enabled=1 where category_id = x;
# 确认配置状态是ok的
select b.key, a.value, a.enabled, a.category_id, a.meta_id from user_settings_setting a, user_settings_settingmeta b where a.meta_id=b.id
and a.category_id=x;
# 3. 恢复部门及用户
update departments_department set enabled=1 where category_id=x;
update profiles_profile set enabled=1, status='NORMAL' where category_id=x;
现象:
日志:
INFO [2023-02-20 14:45:41] 265 disable_profiles_before_sync 29280 140551249217344
Going to mark profiles(and relations)(all: 7955) in category<2> as deleted, skipping 0 profiles
INFO [2023-02-20 14:45:41] 212 _sync 29280 140551249217344
======== Going to bulk_create(count: 236) for Profile =========
INFO [2023-02-20 14:45:41] 225 _sync 29280 140551249217344
======== Syncing part of Profile(1/1) current: 0 + 236 =========
WARNING [2023-02-20 14:45:42] 239 _sync 29280 140551249217344
Profile bulk_create failed, count=236, extra_params={}, will try to sync one by one
ERROR [2023-02-20 14:45:42] 252 _sync 29280 140551249217344
Profile bulk_create: save one by one fail, item=71470-abcdefg-NORMAL, will not be updated, detail={}
Traceback (most recent call last):
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 148, in execute
result = self._query(query)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 310, in _query
conn.query(q)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 775, in _read_query_result
result.read()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 1156, in read
first_packet = self.connection._read_packet()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 725, in _read_packet
packet.raise_for_error()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/protocol.py", line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.IntegrityError: (1062, "Duplicate entry 'f94236485e704bef717341c34d6c81c0d20cc7ad12c916b8cd9960c712db142e' for key 'code'")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser_core/common/db_sync.py", line 232, in _sync
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 503, in bulk_create
objs_with_pk, fields, batch_size, ignore_conflicts=ignore_conflicts,
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 1293, in _batched_insert
self._insert(item, fields=fields, using=self.db, ignore_conflicts=ignore_conflicts)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 1270, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 148, in execute
result = self._query(query)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 310, in _query
conn.query(q)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 775, in _read_query_result
result.read()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 1156, in read
first_packet = self.connection._read_packet()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 725, in _read_packet
packet.raise_for_error()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/protocol.py", line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
django.db.utils.IntegrityError: (1062, "Duplicate entry 'f94236485e704bef717341c34d6c81c0d20cc7ad12c916b8cd9960c712db142e' for key 'code'")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser_core/common/db_sync.py", line 243, in _sync
File "/data/bkce/usermgr/api/bkuser_core/profiles/models.py", line 166, in save
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 740, in save
force_update=force_update, update_fields=update_fields)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 778, in save_base
force_update, using, update_fields,
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 859, in _save_table
forced_update)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 912, in _do_update
return filtered._update(values) > 0
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 802, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql
cursor = super().execute_sql(result_type)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 78, in _execute
self.db.validate_no_broken_transaction()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/base/base.py", line 448, in validate_no_broken_transaction
"An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
ERROR [2023-02-20 14:45:42] 252 _sync 29280 140551249217344
Profile bulk_create: save one by one fail, item=71471-aabbcc-NORMAL, will not be updated, detail={}
Traceback (most recent call last):
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 148, in execute
result = self._query(query)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 310, in _query
conn.query(q)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 775, in _read_query_result
result.read()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 1156, in read
first_packet = self.connection._read_packet()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 725, in _read_packet
packet.raise_for_error()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/protocol.py", line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
pymysql.err.IntegrityError: (1062, "Duplicate entry 'f94236485e704bef717341c34d6c81c0d20cc7ad12c916b8cd9960c712db142e' for key 'code'")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser_core/common/db_sync.py", line 232, in _sync
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 503, in bulk_create
objs_with_pk, fields, batch_size, ignore_conflicts=ignore_conflicts,
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 1293, in _batched_insert
self._insert(item, fields=fields, using=self.db, ignore_conflicts=ignore_conflicts)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 1270, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1416, in execute_sql
cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 148, in execute
result = self._query(query)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/cursors.py", line 310, in _query
conn.query(q)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 775, in _read_query_result
result.read()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 1156, in read
first_packet = self.connection._read_packet()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/connections.py", line 725, in _read_packet
packet.raise_for_error()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/protocol.py", line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/pymysql/err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
django.db.utils.IntegrityError: (1062, "Duplicate entry 'f94236485e704bef717341c34d6c81c0d20cc7ad12c916b8cd9960c712db142e' for key 'code'")
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/data/bkce/usermgr/api/bkuser_core/common/db_sync.py", line 243, in _sync
File "/data/bkce/usermgr/api/bkuser_core/profiles/models.py", line 166, in save
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 740, in save
force_update=force_update, update_fields=update_fields)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 778, in save_base
force_update, using, update_fields,
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 859, in _save_table
forced_update)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/base.py", line 912, in _do_update
return filtered._update(values) > 0
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/query.py", line 802, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql
cursor = super().execute_sql(result_type)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
cursor.execute(sql, params)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/utils.py", line 78, in _execute
self.db.validate_no_broken_transaction()
File "/data/bkce/.envs/usermgr-api/lib/python3.6/site-packages/django/db/backends/base/base.py", line 448, in validate_no_broken_transaction
"An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
查看日志, 每一条用户插入都报错, 并且异常信息都是一致的 pymysql.err.IntegrityError: (1062, "Duplicate entry 'f94236485e704bef717341c34d6c81c0d20cc7ad12c916b8cd9960c712db142e' for key 'code'")
; 这里冲突的code是同一个
排查:
select * from profiles_profile where code='f94236485e704bef717341c34d6c81c0d20cc7ad12c916b8cd9960c712db142e';
找到这个用户, 然后到ldap/mad数据源查找这个用户, 或者咨询人事/ldap或mad维护人员, 最近是否有变更过这个用户的用户名(用户管理ldap/mad 配置中映射到username的字段)
失败原因: ldap/mad 数据同步到用户管理后, username是域下面唯一的, 并且会使用code=sha256(category_id + dn)
作为用户的唯一标识(数据库唯一性约束); 此时如果在数据源变更了某个用户用户名字段(ldap 的cn
或者mad的sAMAccountName
, 取决于配置用户管理目录同步配置的用户名字段
映射到ldap/mad的字段), 再次点同步, 由于username
变了, 但是dn
并没有变, 会导致用户管理当成两个用户进行同步, 但是code
唯一性冲突
修复: 确认对应账号的username
改成什么之后, 在用户管理profiles_profile
表, 需要同步把冲突用户的username
更新为数据源中最新的值, 然后重新进行同步
拉取逻辑:
https://github.com/TencentBlueKing/bk-user/issues/1724
测试是否 MAD / LDAP 查询慢
# Note: LDAP 引入
from bkuser_core.categories.plugins.ldap import login
# Note: MAD 引入
# from bkuser_core.categories.plugins.mad import login
from bkuser_core.profiles.models import Profile
profile = Profile.objects.get(username="xxxx", domain="xxxxx")
l = login.LoginHandler()
l.check(profile=profile, password="xxxxxxx")
背景: ldap由于是外部插件的形式, 内部根本没有场景, 而且ldap server多种多样, 配置差异很大, 非常不好配置; Github issues和社区问答中都存在很多的问题咨询和解答.
目标: 汇总所有相关问题, 并实时更新, 便于用户检索和解决问题
相关入口
如何使用
相关入口
部分的相关文档1/2/3
ctrl+f
在本页搜索相关的关键字, 欢迎补充相关答案相关入口
的`4/5进一步查找(因为更新同步存在延时)欢迎补充相关的 FAQ 及解答, 分享具体实践的经验