Python通过ldap3操作LDAP账号
本次操作服务为
OpenLDAP
,虽然有控制台界面化去操作,但是要实现自动化操作的我们就可以借助ldap3
模块,这是一个严格遵守RFC 4510
规范,完全由纯Python
代码实现的LDAPv3
客户端。直接使用pip
命令安装即可(pip install ldap3
)
一、连接服务器
>>> from ldap3 import Server, Connection, ALL
>>> server = Server('10.10.1.10', get_info=ALL)
>>> conn = Connection(server, 'cn=admin,dc=xxx,dc=xxx', 'xxx', auto_bind=True)
# 获取服务器信息
>>> server.info
通常在对域账号进行修改等操作时,需要启用 SSL
连接以符合安全规范。
>>> server = Server('10.10.1.10', port=636, use_ssl=True, get_info=ALL)
二、对象检索
>>> from ldap3 import Server, Connection, ALL
>>> server = Server('10.10.1.10', get_info=ALL)
>>> conn = Connection(server, 'cn=admin,dc=xxx,dc=xxx', 'xxx', auto_bind=True)
>>> conn.search('dc=xxx,dc=xx', '(objectclass=person)'
>>> print(conn.entries)
[DN: cn=xxx,cn=行政一组,cn=行政组,cn=人事行政部,ou=职能中心,ou=深圳,dc=zen-game,dc=cn - STATUS: Read - READ TIME: 2023-10-26T11:11:45.714743
search
方法有两个参数是必需的:
search_base
用于指定搜索的起始位置,DN
search_filter
用于指定搜索的筛选条件
filter
的定义语法支持 =
、<=
、>=
等比较运算符和 &
、|
、!
等逻辑运算符。如:
(&(cn=John)(mail=*@example.com))
表示寻找名字为 John
且邮箱以 @example.com
结尾的域账号。
以下搜索条件则表示寻找名字为 tony
或 John
,并且邮箱以 @example.com
结尾的域账号:
(&
(|
(cn=tony)
(cn=John)
)
(mail=*@example.com)
)
可选参数 attributes
>>> conn.search('cn=行政一组,cn=行政组,cn=人事行政部,ou=职能中心,ou=深圳,dc=xxx,dc=xx', '(&(objectclass=person)(uid=xxx))', attributes=['gidNumber','uid'])
True
>>> conn.result
{'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'searchResDone'}
>>> print(conn.entries)
[DN: cn=xx,cn=行政一组,cn=行政组,cn=人事行政部,ou=职能中心,ou=深圳,dc=zen-game,dc=cn - STATUS: Read - READ TIME: 2023-10-26T11:37:23.398826
gidNumber: 1816016457
cn: xxx
]
-
判断查询有无可以根据返回结果
True
或conn.result
执行结果来判断 -
(&(objectclass=person)(uid=xxx)
用于指定查找对象类型为person
且uid
为xxx
的用户账号;attributes
参数则用于指定搜索结果中额外包含该账户的gidNumber
、cn
属性。 -
设置
attributes = ['*']
可以在搜索结果中显示对象的所有属性。 -
可以使用
Entry
对象的entry_to_json
方法将该对象的所有属性以JSON
格式输出:
>>> print(conn.entries[0].entry_to_json())
{
"attributes": {
"gidNumber": [
1816016457
],
"uid": [
"summer"
]
},
"dn": "cn=\u6f58\u84c9,cn=\u884c\u653f\u4e00\u7ec5,cn=\u884c\u653f\u7ec4,cn=\u4eba\u4e8b\u884c\u653f\u90e8,ou=\u804c\u80fd\u4e2d\u5fc3,ou=\u6df1\u5733,dc=zen-game,dc=cn"
}
此外还可以使用 paged_size
参数控制每页显示的结果数量。综合实例如下:
>>> conn.search('cn=行政一组,cn=行政组,cn=人事行政部,ou=职能中心,ou=深圳,dc=zen-game,dc=cn', '(&(objectclass=person)(uid=xxx))', attributes=['gidNumber','uid'],paged_size=3)
True
三、更新操作
1. 创建条目
创建用户
>>> dnFullInfo="cn=xxx,cn=行政组,cn=人事行政部,ou=职能中心,ou=深圳,dc=example,dc=com"
>>> userAttr = {
"uid": uid,
"cn": cn,
"sn": uid,
"objectClass": ["top", "posixAccount", "inetOrgPerson", "shadowAccount", "sambaSamAccount"],
"mail": uid + "@example.com",
"shadowWarning": 8,
"userPassword": 111,
"uidNumber": 111,
"gidNumber": 111,
"homeDirectory": "/home/user/" + uid,
"loginShell": "/usr/sbin/nologin"
}
>>> conn.add(dnFullInfo, 'inetOrgPerson', userAttr)
>>> True # 判断这个验证成功还是失败,或者 conn.result 会输出具体信息
创建组
>>> dnFullInfo="cn=行政组,cn=人事行政部,ou=职能中心,ou=深圳,dc=example,dc=com"
>>> groupAttr = {"objectClass": ["posixGroup", "top"], "gidNumber": 111}
>>> conn.add(dnFullInfo, 'posixGroup', groupAttr)
>>> True # 判断这个验证成功还是失败,或者 conn.result 会输出具体信息
2. 修改属性
将【运维组】的gidNumber
参数值改为 613
>>> from ldap3 import MODIFY_ADD, MODIFY_REPLACE, MODIFY_DELETE
>>> conn.modify('cn=运维组,cn=发行平台部,ou=发行系统,ou=深圳,dc=xxx,dc=xxx', {'gidNumber': [(MODIFY_REPLACE, [613])]})
>>> True
3. 组重命名
将【运维组】重命名为【运维组222】
>>> from ldap3 import MODIFY_ADD, MODIFY_REPLACE, MODIFY_DELETE
conn.modify_dn("cn=运维组,cn=发行平台部,ou=发行系统,ou=深圳,dc=xxx,dc=xxx", "cn=运维组222") # 目标RDN(相对路径),用于重命名
>>> True
4. 组移动
将【运维组222】移动到【发行平台部 \ IT组 】下面
格式:源,目的末级名称,目的组织结构,这个移动会携带下面的组成员一块移动
>>> from ldap3 import MODIFY_ADD, MODIFY_REPLACE, MODIFY_DELETE
>>> conn.modify_dn("cn=运维组222,cn=发行平台部,ou=发行系统,ou=深圳,dc=xxx,dc=xxx", 'cn=运维组', new_superior='cn=IT组,cn=发行平台部,ou=发行系统,ou=深圳,dc=xxx,dc=xxx"')
>>> True
>>> print(conn.result)
5. 用户移动
将【tony】用户从运维组移动到【IT组】
>>> from ldap3 import MODIFY_ADD, MODIFY_REPLACE, MODIFY_DELETE
>>> conn.modify_dn("cn=tony,cn=运维组,cn=发行平台部,ou=发行系统,ou=深圳,dc=xxx,dc=xxx", 'cn=tony', new_superior='cn=IT组,cn=发行平台部,ou=发行系统,ou=深圳,dc=xxx,dc=xxx')
>>> True
>>> print(conn.result)
6. 添加用户属性
将【运维组】【memberUid】 属性加 【tony】用户
>>> from ldap3 import MODIFY_ADD, MODIFY_REPLACE, MODIFY_DELETE
>>> conn.modify('cn=运维组,cn=发行平台部,ou=发行系统,ou=深圳,dc=zen-game,dc=cn', {'memberUid': [(MODIFY_ADD, ['tony'])]})
>>> True
>>> print(conn.result)
7. 删除用户或组
>>> conn.delete('cn=运维组,cn=发行平台部,ou=发行系统,ou=深圳,dc=zen-game,dc=cn')
>>> True
>>> print(conn.result)
Reference:
https://ldap3.readthedocs.io/en/latest/
https://github.com/cannatag/ldap3
https://www.jianshu.com/p/07c4d20ae71c