Today I cracked a problem which had troubled us for a while but which I never really sat down and actually tried to troubleshoot. We had an OU with 3rd level admin accounts that no one else had rights to but wanted to delegate certain password related tasks to our Service Desk admins. Basically let them reset password, unlock the account, and enable/ disable.
Here’s some screenshots for the delegation wizard. Password reset is a common task and can be seen in the screenshot itself. Enable/ Disable can be delegated by giving rights to the userAccountControl
attribute. Only force password change rights (i.e. no reset password) can be given via the pwdLastSet
attribute. And unlock can be given via the lockoutTime
attribute.
Problem was that in my case in spite of doing all this the delegated accounts had no rights!
Snooping around a bit I realized that all the admin accounts within the OU had inheritance disabled and so weren’t getting the delegated permissions from the OU (not sure why; and no these weren’t protected group members).
Of course, enabling is easy. But I wanted to see if I could get a list of all the accounts in there with their inheritance status. Time for PowerShell. :)
The Get-ACL
cmdlet can list access control lists. It can work with AD objects via the AD: drive. Needs a distinguished name, that’s all. So all you have to do is (Get-ADUser <accountname>).DistinguishedName)
– prefix an AD: to this, and pass it to Get-ACL
. Something like this:
1 |
Get-ACL AD:$((Get-ADUser rakhesh).DistinguishedName) |
The default result is useless. If you pipe and expand the Access
property you will get a list of ACLs.
1 |
Get-ACL AD:$((Get-ADUser rakhesh).DistinguishedName)| select -Expand Access |
The result is a series of entries like these:
1 2 3 4 5 6 7 8 9 10 |
ActiveDirectoryRights : ReadProperty, WriteProperty InheritanceType : All ObjectType : bf967a0a-0de6-11d0-a285-00aa003049e2 InheritedObjectType : bf967aba-0de6-11d0-a285-00aa003049e2 ObjectFlags : ObjectAceTypePresent, InheritedObjectAceTypePresent AccessControlType : Allow IdentityReference : DOMAIN\User IsInherited : True InheritanceFlags : ContainerInherit PropagationFlags : None |
The attribute names referred to by the GUIDs can be found in the AD Technical Specs.
Of interest to us is the AreAccessRulesProtected
property. If this is True then inheritance is disabled; if False inheritance is enabled. So it’s straight forward to make a list of accounts and their inheritance status:
1 |
Get-ADUser -SearchBase "OU=Admin Accounts,DC=myDomain,DC=com" -Filter * | ft samAccountName,@{Name="InheritBlocked"; Expr={(Get-Acl AD:$((Get-ADUser $_.samAccountname).DistinguishedName)).AreAccessRulesProtected}} |
So that’s it. Next step would be to enable inheritance on the accounts. I won’t be doing this now (as it’s bed time!) but one can do it manually or script it via the SetAccessRuleProtection
method. This method takes two parameters (enable/ disable inheritance; and if disable then should we add/ remove existing ACEs). Only the first parameter is of significance in my case, but I have to pass the second parameter too anyways – SetAccessRuleProtection($False,$True)
.
Update: Here’s what I rolled out at work today to make the change.
1 2 3 4 5 |
Get-ADUser -SearchBase "OU=Admin Accounts,DC=myDomain,DC=com" -Filter * | %{ $ACL = Get-ACL AD:$($_.DistinguishedName); $ACL.SetAccessRuleProtection($false,$true); Set-Acl –AclObject $ACL AD:$($_.DistinguishedName); } |
Update 2: Didn’t realize I had many users in the built-in protected groups (these are protected even though their adminCount
is 0 – I hadn’t realized that). To unprotect these one must set the dsHeuristics
flag. The built-in protected groups are 1) Account Operators, 2) Server Operators, 3) Print Operators, and 4) Backup Operators. See this post on instructions (actually, see the post below for even better instructions).
Update 3: Found this amazing page that goes into a hell of details on this topic. Be sure to read this before modifying dsHeuristics
.