Description
While migrating some users during a Lync migration, I needed to disable users for Lync in one forest, and enable them in another. I ran into a problem where many users in the legacy forest had adminCount set to 1, and security inheritance disabled. The problem is that my account didn’t have rights to disable them in Lync, and I was getting an access denied error. This is common when the user is/was a member of a protected group. I won’t go into the background of adminCount, as it’s well documented.
I knew that as the migration progressed, we would identify more users where this was the case. So I wanted to find a better way of dealing with these. There are several ways of finding users with adminCount set using PowerShell, including
([adsisearcher] "(AdminCount=1)" ).findall() |
and using the ActiveDirectory PowerShell module via
Get -ADuser -LDAPFilter "(admincount=1)" | Select-Object name |
and we can look at groups, too, using
Get -ADgroup -LDAPFilter "(admincount=1)" | Select-Object name |
Turns out that many of the users (1000+) were no longer members of protected groups, what’s often referred to as Orphaned AdminSD Objects. So we could clear adminCount and enable security inheritance. But doing this manually on 1000+ users isn’t something that any of us wanted to spend time doing.
We can clear adminCount with a one-liner:
Get -AdUser [user name] | Set -AdObject -clear adminCount |
But that doesn’t take care of security inheritance, which is the real culprit in my issue. We can use dsacls:
2 | dsacls $User .distinguishedName /p:n |
Unfortunately, this involves multiple steps in native PowerShell. So, a function was born.
Set-AdminUser takes input from either the $UserName parameter, or via the pipeline, and clears adminCount, then enables security inheritance. It can process a single user or multiple, such as with the output of Get-ADGroupMember.
Syntax
Set -AdminUser [[ -UserName ] ] [ -WhatIf ] [ -Confirm ] [] |
Examples
Set -AdminUser [user name] |
Get -AdGroupMember [ group name] | Set -AdminUser |
Code
Here is the function to copy. You can also download it in the download section below.
1 | function Set -AdminUser { |
4 | Clears adminCount, and enables inherited security on a user account. |
7 | Clears adminCount, and enables inherited security on a user account. |
12 | Rights Required : UserAdministrator |
16 | Author : Pat Richard, Skype for Business MVP |
19 | Disclaimer : You running this script means you won't blame me if this breaks your stuff. |
24 | <blockquote class= "wp-embedded-content" data -secret = "Eo5UvfEi8Z" ><a href= "https://www.ucunleashed.com/1621" >Function: Set -AdminUser – Clear AdminCount and Enable Security Inheritance</a></blockquote><iframe loading= "lazy" class= "wp-embedded-content" sandbox= "allow-scripts" security= "restricted" style= "position: absolute; visibility: hidden;" title= "“Function: Set-AdminUser – Clear AdminCount and Enable Security Inheritance” — UC Unleashed" src= "https://www.ucunleashed.com/1621/embed#?secret=BOywIQMFtt#?secret=Eo5UvfEi8Z" data -secret = "Eo5UvfEi8Z" width= "500" height= "282" frameborder= "0" marginwidth= "0" marginheight= "0" scrolling= "no" ></iframe> |
27 | You can pipeline input to this command |
30 | Create the scheduled task to run the script daily. It does NOT create the required Exchange receive connector. |
33 | Set -AdminUser -UserName [user name] |
37 | Clears the adminCount of the specified user, and enabled inherited security |
40 | Get -AdGroupMember [ group name] | Set -AdminUser |
44 | Clears the adminCount of all group members, and enabled inherited security |
49 | [CmdletBinding(SupportsShouldProcess = $True )] |
51 | [Parameter(ValueFromPipeline = $true , ValueFromPipelineByPropertyName = $True , Mandatory = $False )] |
52 | [ValidateNotNullOrEmpty()] |
57 | [bool] $isProtected = $false |
59 | [bool] $PreserveInheritance = $true |
62 | [string] $dn = (Get -ADUser $UserName ).DistinguishedName |
63 | Set -AdObject -identity $dn -clear adminCount |
65 | $acl = $user .objectSecurity |
67 | Write -Verbose "Original permissions blocked:" |
68 | Write -Verbose $acl .AreAccessRulesProtected |
69 | if ( $acl .AreAccessRulesProtected){ |
70 | $acl .SetAccessRuleProtection( $isProtected , $PreserveInheritance ) |
71 | $inherited = $acl .AreAccessRulesProtected |
73 | Write -Verbose "Updated permissions blocked:" |
74 | Write -Verbose $acl .AreAccessRulesProtected |
79 | remove-variable UserName |
80 | remove-variable isProtected |
81 | remove-variable PreserveInheritance |
Donations
I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.
Download
v1.0 – 10-20-2012 Set-AdminUser.v1.0.zip
Follow Me