1. 为什么你天天在"配权限",却依然管不好AD权限
先从一个我见过无数次的场景说起。同事离职,账号要禁用,结果发现这个人的账号在三个不同OU里都有特殊权限,域管理员组里还挂着他的名;另一头,某部门主管申请"给全员开放共享文件夹读取权限",你直接在共享文件夹的ACL里加了"Authenticated Users"——一个月后审计来查,吓了一跳,因为这意味着任何域内合法账号都能读这份资料,里面还有不少财务数据。
这样的场景几乎每周都能遇到。我接触过很多做IT运维的朋友,大家普遍有一个困惑:AD权限体系看起来就几个概念——用户、组、OU、共享文件夹权限,但真正管起来却很累。域控数量多、组织架构复杂、权限分散在不同管理员手里,叠加人员流动,最后往往变成一团乱麻。有人索性把域管密码扔给所有IT同事,大家用同一个administrator账号干活——这简直就是打开了潘多拉魔盒。
这篇博文我想从头梳理AD权限的核心逻辑,讲清楚AD权限到底是什么、怎么生效、常见坑在哪里,再把我自己在实际项目里用的"简化AD权限管理"的方法论拆开来讲。内容适合两类读者:一类是刚接手AD运维的IT管理员,想系统搞懂权限体系;另一类是已经在管AD但被各种权限问题折腾得头疼的工程师,想要一套能落地的治理方案。
先立个调子:管好AD权限,不是把某个OU的委派向导点一遍就完事,而是要建立一套"能说清楚、能查得到、能收得回"的权限视图。所谓"能说清楚",是任何一条权限都能讲明白为什么存在;"能查得到",是随便找一个账号或OU,能马上列出它的全部有效权限;"能收得回",是人走、岗变、项目结束时,权限能及时回收。后面所有的方法论和实操,都是围绕这三点展开的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. AD权限体系的底层逻辑:SID、ACL、继承和委派
2.1 权限生效的最小单元:SID与访问令牌
要理解AD权限,先理解SID(Security Identifier,安全标识符)。SID是域内每个安全主体(用户、计算机、安全组)在创建时被分配的唯一标识,作用类似身份证号。你在AD里改用户名、改所属组织,SID始终不变——这保证了用户改名前后的权限关系不会断掉。
当用户登录域时,域控会签发一个访问令牌(Access Token),里面除了用户自己的SID,还包含用户所属的所有安全组的SID。系统在做权限校验时,不是去查"用户A属于哪些组、这些组有没有权限"这么绕的关系,而是直接把令牌里所有SID和资源的ACL比对,命中哪个SID,就按对应的ACE(Access Control Entry,访问控制项)生效。
这个机制引出一个非常关键的认知:AD权限判断的时间点是"登录时"。用户登录后加入的新组,不会立刻生效,需要重新登录或运行klist purge(清除Kerberos票据缓存)后再重新登录。反过来,如果用户从某个组中被移除,只要旧的访问令牌没失效,他理论上仍能继续访问部分资源,直到令牌过期或重新登录。这个问题在排查"为什么他刚被踢出组还能访问共享文件夹"时特别容易踩坑。
2.2 DACL、SACL、ACE:权限安全描述符的结构
每个AD对象(用户、组、OU、共享文件夹、打印机)都挂着一个安全描述符(Security Descriptor),里面包含四个主要部分:
| 组成部分 | 作用 | 日常管理中的意义 |
|---|---|---|
| Owner(所有者) | 默认为创建者,拥有读取和修改DACL的权利 | 权限配置混乱时,可用所有者权限修复 |
| DACL(自主访问控制列表) | 规定谁能对该对象做什么操作 | 最常打交道的部分,理解权限的关键 |
| SACL(系统访问控制列表) | 定义审计策略,记录哪些访问会被写入审计日志 | 等保合规和入侵溯源的核心 |
| 对象附加信息 | 如对象类型、创建时间等 | 主要用于扩展属性 |
ACE是ACL里的每一条规则,格式大致为"主体(SID) + 权限类型(允许/拒绝) + 具体操作 + 是否继承"。AD和NTFS文件系统的ACL结构基本一致,因此很多管理经验可以互相借鉴。
一个经常让人困惑的点是"拒绝(Deny)"ACE。系统在权限评估时的顺序是:先处理所有Deny,再处理Allow。也就是说,只要一条Deny ACE命中,无论其他Allow ACE给了多大权限,最终结果都是拒绝。这个特性在"必须封禁某个例外账号"时很有用,但也容易成为权限排查的拦路虎——一条隐藏的Deny会让所有Allow全部失效,还很难一眼看出来。
2.3 权限继承:省事与失控的分界线
AD权限默认是向下继承的。你在域根OU上给某组委派了"重置密码"权限,那么下方所有子OU和用户对象都自动获得这个权限。这个机制极大降低了初始部署时的配权限工作量,但也带来了一个隐患:很多人根本不知道自己域里有多少"看不见的继承权限"在生效。
举个例子,某公司为了让IT支持人员能重置全员密码,在域根OU上给"IT Service Desk"组委派了"重置密码"。这个设计在初期没什么问题,但后来公司架构调整,某个子OU因为合规要求必须严格管控,只有HRBP才能重置密码。结果一查,IT Service Desk对那个子OU依然有重置密码的权限——因为继承的权限在子OU上依然生效。这个权限如果没被发现、没被显式阻断,就会一直挂在那里。
解决继承失控的标准手段是"阻断继承"(Block Inheritance)。ADUC里打开OU属性,可以在"安全"标签页把"允许从父对象继承权限应用到该对象"的勾去掉。但要注意,阻断继承是双刃剑:一旦阻断,父级所有权限(包括域管权限)都不再向下应用,如果该OU下没有显式配置管理员权限,可能连域管理员都会被锁在外面。正确做法是先记录原有ACL,再阻断,然后逐条补上必要的权限。
2.4 委派控制:微软官方给出的"最小权限"实践
委派(Delegation)是AD权限管理里一个非常核心的概念,本质上就是"把OU范围内的一部分管理操作交给某个组/用户,而不是全都交给Domain Admins"。典型操作是ADUC右键OU,选择"委派控制",在弹出的向导里选择要委派的权限,比如"创建、删除和管理用户账户""重置密码并强制下次登录时修改密码""读写指定GPO的筛选器"等。
从我经手的项目看,委派用得好的团队,域管组成员数量可以控制得很小(比如全公司就3个人),IT服务台通过被委派的组完成日常账号操作。委派用不好的团队,域管组里挂着一堆人,个个都有全域管控权,出了安全问题根本没法追责。
委派设计的核心原则就一句话:域管管"目录本身",委派管"目录里的业务"。域管负责加域控、改架构、做组策略核心配置;委派组负责某个OU的用户增删改、密码重置、组成员调整。这个边界如果模糊,权限就会迅速膨胀。
3. 动手查权限:三条最有效的排查路径
3.1 ADUC的"高级功能"不是只能看,要会用
很多管理员知道ADUC里的"查看->高级功能"能打开对象的"安全"标签页,但只知道看,不知道怎么高效利用。打开用户或OU的"安全"页后,你会看到一长串ACL条目,但要判断"某个用户对某OU到底有没有Manage Password权限",直接凭肉眼翻列表是不够的。
关键在"高级"按钮里的"有效访问"功能。输入一个用户或组,勾选"查看有效访问",系统会基于对象当前所有ACL(包括从父级继承来的)给出一个经过综合评估的权限结果。这个功能比一条条看ACE效率高得多,排查"谁还能改谁"这类问题时尤其好用。
但"有效访问"不是万能的。它评估的是对象在域内的静态权限,不会帮你预测"未来"——比如用户被加入某个域本地组后对资源的新权限,或者拒绝ACE生效后就改变的结果。这种动态变化需要结合组成员关系来推理。
3.2 命令行三件套:dsacls、Get-Acl、Get-ADPermission
如果要写脚本批量导出权限清单,命令行是必然选择。我用得最多的三个命令:
dsacls:查看AD对象的DACL,输出格式和ADUC里的ACL列表高度对应。例如查看某个OU的权限:dsacls "OU=财务部,DC=contoso,DC=com"。Get-Acl:PowerShell里的通用ACL获取命令,配合ActiveDirectory模块可以得到对象安全描述符,再通过Access属性输出ACE。Get-ADPermission:Exchange管理工具里的命令,更偏向资源邮箱/共享邮箱的权限查看,但它的输出格式更友好,有些场景比dsacls更清晰。
实际排查时,我通常习惯先看是否有隐藏的继承阻断或Deny ACE。例如,把dsacls的输出导出来搜索一下"Deny"关键字,往往比在GUI界面里翻半天更有收获。
一段常用的导出脚本示例:
powershell复制Import-Module ActiveDirectory
$ou = "OU=财务部,DC=contoso,DC=com"
Get-Acl -Path "AD:$ou" |
Select-Object -ExpandProperty Access |
Format-Table IdentityReference, ActiveDirectoryRights, AccessControlType, IsInherited -AutoSize
输出的IdentityReference列会显示SID或账号名,ActiveDirectoryRights会显示具体权限(如ResetPassword、WriteMember等),IsInherited则能区分哪些权限来自父级继承,哪些是本地显式配置。
3.3 权限路径分析:用BloodHound做全域权限可视化
虽然BloodHound更多被安全研究圈使用,但它在日常AD权限治理中的作用被低估了。BloodHound能自动抓取域内的ACL、组成员关系、GPO链接和会话关系,然后用图数据库的方式呈现"谁能通过哪条路径拿到哪里的权限"。
平时排查"这个普通用户能不能拿到域管权限"这类问题时,BloodHound的可视化路径分析能力远胜手动翻ACL。它给出的路径可能是:普通用户 -> 拥有对某组的GenericAll权限 -> 利用该组嵌套关系 -> 拥有了对Domain Admins组的WriteDACL权限 -> 改写域管组ACL -> 加入自己。这种"借道"式提权,纯手工排查很难发现。
BloodHound不是银弹。它的快照依赖于抓包时机,数据过期后准确性会下降;而且如果域内ACL本身设计得很混乱,它会画出无数条路径,反而增加噪音。我建议把BloodHound当作周期性权限审计的辅助工具,比如每个季度跑一次,对比前后快照差异,用来验证"上一轮权限治理是否有效"。
4. 高效管理AD权限的实操抓手:模型、矩阵与最小化
4.1 用嵌套组和AGDLP把权限收拢成"组"的集合
AD权限管理最核心的简化手段,就是把"人"的权限关系变成"组"的权限关系。人只是组的成员,而组才挂权限。这样人员离职、转岗时,只需调整组成员关系,一天可以处理几十个账号,而不是去翻几十个OU和共享文件夹的ACL。
这里必须提到AGDLP原则:A(Account)账号放到G(Global Group)全局组,全局组放到DL(Domain Local Group)域本地组,域本地组挂权限(P,Permission)。简化理解就是:全局组对应"岗位/角色",域本地组对应"资源权限"。比如"财务部会计"全局组加入"财务系统读写"域本地组,而"财务系统读写"域本地组拥有对财务共享文件夹ACL的修改权限。
好处有两个。第一,权限和人员解耦,人员流动时只需动全局组成员;第二,跨域资源授权变得简单,全局组可以跨域放,域本地组只在本域生效。
但AGDLP也有反面教训。组层级嵌套过深(例如超过3~4层)会让权限追踪变得非常困难,"这个组为什么能访问这个文件夹"需要一层层往上翻。我见过一个极限案例:一个生产系统权限组嵌套了7层,中间还混着好几个安全组,最后排查一个越权访问问题时整整花了两个星期。所以AGDLP不是无限嵌套,而是要控制层级深度,尽量让组的设计可读。
4.2 设计一份"角色-权限-对象"矩阵再动手
很多AD权限混乱的根源,在于"边想边配"——临时需要就给某个人加权限,不记录、不归类。正确姿势是先设计角色权限矩阵,再动手配置。
举个实际例子。假设公司给IT服务台设计三类角色:
| 角色 | 管理范围 | 敏感操作 | 典型权限 |
|---|---|---|---|
| L1支持 | 指定OU | 重置密码、解锁账号、启停账号 | ResetPassword、Unlock、Enable/Disable |
| L2工程师 | 指定OU | 创建/删除用户、调整组成员 | Create/Delete User、Write Member |
| 安全审计 | 只读 | 查看ACL、登录日志 | Read Security Settings、登录审计日志读取 |
矩阵设计好后,落地步骤就变成:
- 为每个角色创建对应的全局安全组,如
G_L1_Helpdesk、G_L2_Support、G_Auditor。 - 将人员加入对应全局组。
- 在所需OU上执行"委派控制"向导,按矩阵勾选权限,勾选时把能用的权限尽量收窄,避免"允许完全控制"这种粗粒度选项。
- 在组策略或系统层面,对需要操作服务器的场景再单独授权。
这个流程看似多了一步"设计",但它带来的收益是划时代的:后来任何权限评审,都可以拿着矩阵对比实际AD配置问一句"为什么有这个偏差点"。
4.3 定期做权限集中评审与收缩
仅有设计还不够,AD权限会自然"长胖"。每次业务系统上线、IT人员临时支援、外包工程师入场,都会留下一些临时权限,项目结束之后没人记得回收。建议至少每季度做一次集中评审,重点就三个维度:
- 无效账号:离职且未禁用、超过90天未登录、重复账号。
- 过度授权:普通用户账号是否意外加入管理员组;域管组成员是否超过业务必需;GPO链接和筛选器是否被意外改动。
- 异常ACL:OU和共享文件夹里出现非预期Deny、异常所有权变更、出现非标准安全主体(如计算机账号或service账号挂权限)。
评审动作本身,可以用脚本辅助。从我的经验看,最有效的组合拳是"PowerShell脚本导出+Excel/WPS透视表对比":
powershell复制Get-ADGroupMember -Identity "Domain Admins" | Select Name, SamAccountName, ObjectClass
Get-ADUser -Filter * -Properties LastLogonDate |
Where-Object { $_.LastLogonDate -lt (Get-Date).AddDays(-90) -and $_.Enabled } |
Select Name, SamAccountName, LastLogonDate
把这些输出交给业务负责人确认,比审计时向域控日志讨要解释要省心得多。
4.4 做好"最小权限"的两类补充:GPO与SCM,但别混淆
AD权限管理经常和GPO权限混在一起。需要强调:GPO(组策略)是一种配置管理机制,不是身份权限体系,但GPO本身也有ACL,控制谁能编辑、谁能套用。管AD权限时,如果忽略GPO的ACL,很可能出现"某个普通用户意外拥有GPO编辑权"的隐患。
我的建议是:把GPO的ACL纳入权限清单统计范围,但与身份权限分开管理。GPO编辑权限默认只给Domain Admins和Enterprise Admins,如果业务需要给某个组委派GPO编辑权,尽量用专门的"Policy Manager"组,并明确被管理的GPO范围,避免整个域的GPO都能被改。
另外,SCM(System Center Management)这类基础架构工具的权限,也建议遵循同一套"角色-权限-对象"矩阵,不要例外。很多人域权限管得不错,但服务器本地管理员组里塞满了服务账号,最后被人横向提权,就是这类遗漏的代价。
5. 那些年我们都踩过的AD权限坑:三条高发案例复盘
5.1 "为什么他刚被移出组还能访问":缓存令牌的迷惑性
这是典型的"权限移除不生效"问题。从AD角度看,用户已经从组中被移除,ACL也匹配不到对应SID了;但从用户角度,他的Windows会话和Kerberos票据还在有效期内,访问令牌里依然保留了旧组SID,所以看起来"权限仍然存在"。
这种坑在排查共享文件夹越权时最常见。正确的验证方法不是让用户反复刷新,而是让用户重启会话或执行:
cmd复制:: 清除当前会话的Kerberos票据和缓存
klist purge
:: 之后重新登录/重新映射网络驱动器
从管理端出发,如果业务要求"移除即失效",需要用更强的控制手段,例如在共享权限层面直接删掉该用户的显式ACL,或者在账号上临时禁用一段时间,而不是只从组里踢出。我在做客户项目时,经验是"权限移除后,静默等待安全策略中的重新授权周期,再做二次复核",这样既照顾业务连续性,又避免了权限残留在审计上说不清。
5.2 "域管登不上这台服务器了":继承阻断引发的意外收缩
我接过一个求助:某IT同事在某个业务OU上做了"阻断继承",结果半天后,域管组访问那台服务器的能力消失了,服务也起不来了。打开ACL一看,原来这个OU下面有一台重要服务器,管理员此前一直靠"域管组自动继承权限"来管理它。阻断继承后,这条继承路径消失了,新ACL里又没有显式加入Domain Admins,导致管理失灵。
正确操作是:在计划阻断继承前,先导出该OU下所有对象的ACL,并整理出必需权限清单,再阻断,最后逐条手动添加。哪怕只是临时加一条"Domain Admins完全控制",也能避免管理断链。
还有一个衍生教训:阻断继承不能当"默认动作",只在合规要求明确、对象边界清晰的场景下才用。大多数情况下,通过控制父级ACL的范围来收缩权限,比阻断继承再重建一套ACL要安全得多。
5.3 "密码重置委派给了子OU,但用户账号在父OU":委派范围不匹配
委派控制的粒度是"OU范围",很多人在设计时只考虑组织架构,没考虑对象位置。比如"财务部新员工入职需要重置密码",你给"财务部"子OU委派了重置密码权限,但一个跨部门调动的账号还在原部门OU里,或者一个service account在"Managed Service Accounts"OU下,IT服务台就没有权限处理它。
这类问题没有银弹,只能靠设计阶段避免。建议事先梳理所有账号类别和所在OU,把委派范围设置成"可能发生操作"的OU集合,而不是按组织矩阵画一个漂亮但无用的边界。同时,在系统上线前,至少选几个代表性场景做"影子测试",用普通委派组账号登录试操作一遍,而不是只争论文档。
6. 从"人肉配权限"到"自动化管理":用脚本和流程兜底
6.1 把重复性权限申请变成自助服务或脚本模板
权限管理最大的成本是"走流程"。一个同事换岗或入职,至少要经历"业务确认->IT审批->操作执行->审计复核"四步。如果每步都靠邮件和聊天软件通知,审计追溯就是灾难。
比较好的实践是:在ITSM工单系统里,把权限申请做成标准服务目录,比如"账号创建(含默认组)""加入XX业务组""重置密码""临时权限延期"。每个服务目录关联到后台的PowerShell脚本,审批通过后由自动化平台拉取参数执行。这样既保留了审计记录,又减少了人工漏配和误配。
6.2 不用花钱也能用的自动化脚本框架
即使没有商业化平台,也可以在半自动状态下跑脚本。我的方案是"脚本 + 计划任务 + 日志"三件套:
- 所有权限变更操作统一通过函数执行,禁止管理员直接在ADUC里手点;
- 每次变更写日志文件,格式包含操作者账号、时间、对象、权限、审批单号;
- 每周执行一次对比任务,把当前全量权限清单与上周末的基线清单做diff,发现差异自动发邮件提示。
一段辅助"创建用户并加组"的脚本:
powershell复制# 示例:为新员工创建域账号并加入标准组
$userInfo = @{
Name = "张某某"
SamAccountName = "zhang.mou"
UserPrincipalName = "zhang.mou@contoso.com"
GivenName = "张"
Surname = "某某"
Path = "OU=新员工,OU=IT运维部,DC=contoso,DC=com"
AccountPassword = (ConvertTo-SecureString "初始密码123!" -AsPlainText -Force)
Enabled = $true
}
New-ADUser @userInfo
Add-ADGroupMember -Identity "G_L1_Helpdesk" -Members "zhang.mou"
# 记录审计
"$(Get-Date) - 创建账号 zhang.mou, 由 $env:USERNAME 操作" | Out-File -Append D:\ADChangeHistory\account_creation.log
这类脚本虽然不复杂,但能显著减少误操作。至于更高级的能力(例如权限到期自动回收),可以给组加mangement属性,定期用脚本扫描过期标记,再联动禁用或移除。
6.3 权限变更的"双人复核"机制比想象中更重要
自动化不是万能药,权限变更的"双人复核"(四眼原则)依然重要,甚至比自动化更能兜底。做法是:申请人在工单系统提交,直属领导审批,IT操作员执行,独立审计员或管理员抽检。这个流程不需要复杂系统,手工记录表单+仪表盘即可,但能保证权限变更存在一个"外部视角"。
我自己的例行做法是:每月初导出一份"上月权限变更汇总",不只看是否有误配,还顺手找找是否有过度授权的情况。有一次我抓到一个月前的"管理员把Domain Admins组临时加给外包工程师,但忘了移除"的记录,幸亏当时还开了审计日志,不然真等项目验收再发现,性质就不一样了。
7. 写在最后:简化AD权限管理,本质是把人从手工里解放出来
做完一次AD权限治理项目后,我最深的体会是:管权限不是"技术活",而是"管理活"。技术本身很简单——SID、ACL、嵌套组、委派,这些概念半天就能讲完;真正难的是让整个团队形成一套统一的权限管理习惯,并把流程固化成"哪怕换个人也跑得动"的样子。
如果你所在的组织还在靠"拍脑袋"配权限,我的建议是别急着上复杂工具,先做三件事:把域管组成员删到最少;给IT服务台做一个标准委派组;每季度跑一次权限清单导数和比对。这三板斧落地后,你会明显感觉到权限问题数量下降一个量级。
最后再分享一个我真实的经验:在一次域迁移项目中,客户让我评估他们的权限现状,我跑了半个月脚本之后发现,真正有效、被业务实际使用的权限只占全部ACL的三分之一,另外三分之二要么是历史遗留、要么是重复授权、要么是无效嵌套。当我们把这三分之二清理掉、把余下的纳入统一角色矩阵后,系统的性能、审计通过率、管理员的幸福感都同步提升了。权限管理从来不是"越多越好",而是"越清楚越好"。
