AD域建设管理(二)| python3+ldap3管理AD域实践(批量创建OU、用户、改密码、更新OU与用户)

AD域建设管理(二)| python3+ldap3管理AD域实践(批量创建OU、用户、改密码、更新OU与用户)

最后更新: 2020/5/31
更新说明: 本文只写使用文档和截图说明;源码地址RandolphCYG / husky_ad ,当发现问题的时候,及时更新提代码;

系列博客

1.使用前提

1.1.关于程序运行环境

这里是主要的python炸药包及介绍,后面会优化安装方式

项目 描述
python3 主要后端开发语言
ldap3 是一个十分优秀且稳健的对active directory域进行管理的炸药包
pandas 代替python的原生文件读取包,提高处理效率
winrm 用来远程连接windows server执行powershell命令

1.2.关于AD域的准备和配置

【注意】本文均启用ssl安全连接AD域,需要先安装AD证书服务
如果还没来得及安装AD证书服务,需要将程序中use_ssl参数改成use_ssl=False,但此时建立的ldap连接不可以做修改密码操作(未做判断);
很多博客讲的是LDAP3的CAUD基本操作,而我作为一个实践过上线了的AD域的实践者,会偏向于总结从无到有的整个经历的过程;

2.问题和解决方案

2.1.安全考虑——防止对象被意外删除

  • 位置:ADSI编辑器>OU右键属性>对象>防止对象被意外删除
  • 作用:勾选之后,不可直接将该对象删除,默认不启用

为了保证生产服AD域的组织架构的安全性,需要严格控制OU的是否可以直接被删除的属性;
最初做的时候,是想批量生成多级OU,然后在AD服务器打开powershell执行一下几条命令设置防止对象被意外删除属性;
后面为了简化操作,使用python的winrm炸药包远程连接AD域服务器并执行powershell命令;
在这里插入图片描述

  • 启用(勾选):
# 启用ActiveDirectory模块
Import-Module ActiveDirectory
# 查询没有启用对象被意外删除的OU
Get-ADOrganizationalUnit -filter * -Properties ProtectedFromAccidentalDeletion | where {$_.ProtectedFromAccidentalDeletion -eq $false} | ft
# 查询没有启用 对象被意外删除的OU 属性,并设置为启用
Get-ADOrganizationalUnit -filter * -Properties ProtectedFromAccidentalDeletion | where {$_.ProtectedFromAccidentalDeletion -eq $false} |Set-ADOrganizationalUnit -ProtectedFromAccidentalDeletion $true

在这里插入图片描述
这样如果直接对OU删除的话会提示:
同样,用程序也就不能任意的删除OU了;
在这里插入图片描述

  • 不启用(不勾选):
Import-Module ActiveDirectory
Get-ADOrganizationalUnit -filter * -Properties ProtectedFromAccidentalDeletion | where {$_.ProtectedFromAccidentalDeletion -eq $true} | ft
Get-ADOrganizationalUnit -filter * -Properties ProtectedFromAccidentalDeletion | where {$_.ProtectedFromAccidentalDeletion -eq $true} |Set-ADOrganizationalUnit -ProtectedFromAccidentalDeletion $false

程序中设计:
传进来的flag用来选择执行那个命令列表flag_map[flag],flag给0 则执行enable_del列表中的命令,不勾选这个属性;
每次修改完OU之后都会给flag传1,勾选此属性;

# powershell命令 用于启用/关闭OU 防止对象被意外删除 属性
# 防止对象被意外删除×
enable_del = ["Import-Module ActiveDirectory",
              "Get-ADOrganizationalUnit -filter * -Properties ProtectedFromAccidentalDeletion | where {"
              "$_.ProtectedFromAccidentalDeletion -eq $true} |Set-ADOrganizationalUnit "
              "-ProtectedFromAccidentalDeletion $false"]
# 防止对象被意外删除√
disable_del = ["Import-Module ActiveDirectory",
               "Get-ADOrganizationalUnit -filter * -Properties ProtectedFromAccidentalDeletion | where {"
               "$_.ProtectedFromAccidentalDeletion -eq $false} |Set-ADOrganizationalUnit "
               "-ProtectedFromAccidentalDeletion $true"]
flag_map = {0: enable_del, 1: disable_del}

测试案例:
执行ad.ad_update(RAN_EXCEL)更新AD域,假设AD域还没有组织,没有用户,会自动判断上级OU不存在,会先创建上级几层OU,设置防止对象被意外删除,然后创建用户,保存账号和密码。
在这里插入图片描述

  • 其他拓展 目前没找到也就没用到
    ProtectedFromAccidentalDeletion设置为true的即启用防止对象被意外删除
    ProtectedFromAccidentalDeletion设置为false则不启用防止对象被意外删除

2.2.安全考虑——修改用户密码

2.2.1.最初的探究

  • 探究发现,在批量创建用户并设置启用用户后,每一个用户的密码默认是空。
    这里我修改了5***与2***密码,都是空
    在这里插入图片描述

2.2.2.如何修改密码?

最开始,决定用程序初始化/修改用户密码时遇到了问题,对一个测试用户右键查看属性,里面有字段userPassword,手工赋值后该密码并没有起到作用,通过查询国外文档,找到了原因所在:

  • 根据下面文章,我们知道AD域将用户密码存储在unicodePwd属性中,而不是userPassword中,因此,在创建用户的时候,不需要给userPassword字段赋值;
  • unicodePwd属性不可查询,需要建立ssl安全通道才能进行修改,否则只能在服务器用**Set-ADAccountPassword -Identity 【DN】**修改;
  • 方案1这里若域还没有配置安装证书服务,636安全端口不能连接,只能在AD域服务器跑powershell脚本对用户批量设置密码【已实现】
  • 方案2若配置了安装证书服务,则使用self.conn.extend.microsoft.modify_password(dn, new_pwd, old_pwd)完成对密码的修改/初始化;

Active Directory中的LDAP密码更改
2010年8月26日/ 尼尔·威尔逊

我从未真正热衷于Active Directory。Microsoft倾向于将标准更像是建议而不是规则,而Active Directory则提供了一些很好的例子。最近有人问我一个问题,关于如何通过LDAP更改Active Directory中的密码。在大多数目录服务器中,您要么使用LDAP密码修改扩展操作(如RFC 3062中所述),要么执行简单的修改操作以将明文密码替换userPassword属性(服务器将自动执行任何操作)。必要的编码来掩盖该值)。但是,Active Directory有许多非常不寻常的要求,因此可能值得一提。它们包括:

  • Active Directory似乎不支持密码修改扩展操作,因此您必须使用常规LDAP修改操作来更改密码。
  • Active Directory将密码存储在unicodePwd属性中,而不是userPassword中
  • Active Directory仅接受通过安全连接的密码更改。我只用过SSL。也许您也可以使用StartTLS或具有机密性的SASL,但是我不确定。
  • 新密码必须用引号引起来,并且必须使用UTF-16 little-endian编码。
  • Active Directory可能会对密码施加一些强度要求,尽管这些要求的确切含义可能因一个实例而异。

知道了这些要求之后,您应该能够使用允许您在Active Directory中执行密码更改的任何LDAP API编写代码。

2.2.3.pwdLastSet 密码过期相关

参考文章:LDAP pwdlastset unable to change without error showing

pwdLastSet属性查询出来的是时间,但是却不能修改为datetime/timestamp类型,会报错为00000057:SysErr:DSID-031A122C,problem 22(Invalid argument),data0 我在程序中测试的时候,现在AD域修改一个用户的密码,然后查到此属性的值时间戳,而且这个时间戳开始时间是不恰当的,用程序给用户直接修改这个值就会报错,是因为——

仅系统可以将pwdLastSet属性修改为0或-1以外的任何值。如果分配0,则密码立即失效。然后,当用户更改密码时,系统会将当前日期/时间分配给pwdLastSet属性。
值-1对应于64位属性2 ^ 63-1中允许的最大整数。此值取反0。它使密码未过期。当用户下次登录时,系统会将pwdLastSet属性设置为与当前日期/时间相对应的值。

  • 说明pwdLastSet-1——使得密码不过期;pwdLastSet0——密码立即失效;
  • 最终方案modify_res = self.conn.modify(dn, {'pwdLastSet': (2, [-1])}) # pwdLastSet只能给-1 或 0

2.2.4.AD域用户密码策略

  • 位置:服务器管理器>工具>组策略管理>域的默认策略>右键编辑>组策略管理编辑器>找到密码策略;
  • 小点:如果默认域策略灰禁不能编辑,去搜一下,忘记了;
  • 注意根据需要修改密码策略,如果之后都不想让密码过期,只需将密码最长使用期限数值改成0;
    20200403170150232

3.源码及使用说明

最新版及使用文档优先在源码READ.MD文档中更新
源码地址RandolphCYG / husky_ad
本文将重点放在生产上遇到的问题和解决策略以及我在本地的实践;

3.1使用案例(待补全)

稍微提一下功能及步骤:

  1. 从表格读取数据,充分扫描表格数据是否有问题,通过后返回同步AD域用户的元数据
  2. 开始更新AD域,如果该用户已经在域中切信息未变则忽略/变化则修改、该用户不在域中则新增并将用户密码保存在pwd.txt中、然后设置第一次登录必须修改密码
  3. 前两步骤都是ad.ad_update(RAN_EXCEL)一行封装的操作,接下来可选的是——1.扫一下AD域有没有空OU处理下ad.scan_ou() / 2.扫一下AD域在表格中不存在的用户判断为离职人员将其禁用并移动到DISABLED_BASE_DN = 'OU=resigned,DC=randolph,DC=com' # 离职账户所在OU 该功能调用方式为ad.disable_users(RAN_EXCEL)
  4. 其他:ad_update操作在需要从表格更新AD域的时候都可使用、会补充晚上密码过期策略的方案、发送精美邮件及控制发送范围的功能
  5. 纯新增员工操作需要调用ad.create_user_by_excel(NEW_RAN_EXCEL),NEW_RAN_EXCEL是新员工表格的地址,可以在表格中填写用户(多个),然后执行此功能即可,账号密码会自动在pwd.txt中新增

拓展任务:更新AD域后,OU架构可能会因为公司架构而变化,那么手工设置的管控不同OU的admin管理员账户则需要重新检查

3.1.1初始化/更新AD域

必要条件:用于初始化/更新AD域的表格一定是全量的(包含所有的公司员工);不然之后会将AD域中有的,表格中没有的用户判断为离职员工进行处理;
如何使用
1.修改基础信息并在main中用ad = AD()测试AD域连通性,检查info.log中是否出现INFO localAD.py 71 distinguishedName:CN=Administrator,CN=Users,DC=randolph,DC=com res: True即连接成功的标志
在这里插入图片描述
2.解开ad.ad_update(RAN_EXCEL)一行的注释,执行即可
可以先用一个用户的更新流程做个判断
在这里插入图片描述
for循环打个break测试下,后面考虑将各步骤的测试写成一次性的检测机制;
在这里插入图片描述
若在info.log看到有用户创建成功并在pwd.txt中生成了账号密码,则可将break语句删掉,直接跑代码了;
问题:我发现日志记录的太多了,会让程序运行中花费更多时间在日志记录上,虽然有利于后面的排查与参考,但是会影响执行速度;实验的环境为2000位用户、十几个OU、三四层级OU的更新,附带对AD域服务器远程执行powershell和日志文件和密码文件的读写,耗费时间足足两分钟;【暂时想到优化的方法,将powershell命令修改成每次更新前后执行两次,而不是每位用户的各级OU的修改都会执行两次!】
从日志中可以看到——
AD域连接成功:
在这里插入图片描述

最后一位用户创建成功
在这里插入图片描述

账号密码文件:
在这里插入图片描述

ran_list.xlsx原始表格是这样的:
在这里插入图片描述
用于新增用户的表格文件new_ran_list.xlsx格式也是一样的:
在这里插入图片描述

3.1.2新增用户

需要新增用户的话,这么操作:
在这里插入图片描述
效果:
在这里插入图片描述
账户密码已经创建成功:
在这里插入图片描述
提一下密码规则generate_pwd(count)函数:count为密码位数,密码为复杂密码——随机密码,必有数字、大小写、特殊字符且数目伪均等;

猜你喜欢

转载自blog.csdn.net/qq_33997198/article/details/105297121