Function: Set-AdminUser – Clear AdminCount and Enable Security Inheritance
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 name
and we can look at groups, too, using
Get-ADgroup -LDAPFilter "(admincount=1)" | select 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:
$User = [ADSI] $_.Path 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.
function Set-AdminUser {
<#
.SYNOPSIS
Clears adminCount, and enables inherited security on a user account.
.DESCRIPTION
Clears adminCount, and enables inherited security on a user account.
.NOTES
Version : v1.0
Wish list :
Rights Required : UserAdministrator
Sched Task Req'd : No
Lync Version : N/A
Lync Version : N/A
Author : Pat Richard, Exchange MVP
Email/Blog/Twitter : pat@innervation.com http://www.ehloworld.com @patrichard
Dedicated Post : http://www.ehloworld.com/1621
Disclaimer : You running this script means you won't blame me if this breaks your stuff.
Info Stolen from : http://serverfault.com/questions/304627/powershell-script-to-find-ad-users-with-admincount-0
: http://morgansimonsen.wordpress.com/2012/01/26/adminsdholder-protected-groups-sdprop-and-moving-mailboxes-in-exchange/
.LINK
http://www.ehloworld.com/1621
.INPUTS
You can pipeline input to this command
.PARAMETER UserName
Create the scheduled task to run the script daily. It does NOT create the required Exchange receive connector.
.EXAMPLE
Set-AdminUser -UserName [user name]
Description
-----------
Clears the adminCount of the specified user, and enabled inherited security
.EXAMPLE
Get-AdGroupMember [group name] | Set-AdminUser
Description
-----------
Clears the adminCount of all group members, and enabled inherited security
#>
#Requires -Version 2.0
[CmdletBinding(SupportsShouldProcess = $True)]
param (
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $True, Mandatory = $False)]
[ValidateNotNullOrEmpty()]
[string]$UserName
)
Begin{
## allows inheritance
[bool]$isProtected = $false
## preserves inherited rules
[bool]$PreserveInheritance = $true
}
Process{
[string]$dn = (Get-ADUser $UserName).DistinguishedName
Set-AdObject -identity $dn -clear adminCount
$user = [ADSI]"LDAP://$dn"
$acl = $user.objectSecurity
Write-Verbose $dn
Write-Verbose "Original permissions blocked:"
Write-Verbose $acl.AreAccessRulesProtected
if ($acl.AreAccessRulesProtected){
$acl.SetAccessRuleProtection($isProtected,$PreserveInheritance)
$inherited = $acl.AreAccessRulesProtected
$user.commitchanges()
Write-Verbose "Updated permissions blocked:"
Write-Verbose $acl.AreAccessRulesProtected
}
}
End{
remove-variable acl
remove-variable UserName
remove-variable isProtected
remove-variable PreserveInheritance
remove-variable dn
remove-variable user
}
} # end function Set-AdminUser
Download
v1.0 – 10-20-2012 Set-AdminUser.v1.0.zip



Great script. If I can make a recommendation, I’d add a version for those still on Windows 2003 domains that could use the Quest ActiveRoles Shell. Replacing the set-ad* commands with set-QAD*.
The problem is that that would require a third party solution (Quest ActiveRoles) be installed. My scripts don’t typically require something like that, as mine are created with the goal that someone could come into another orgs environment and use the scripts without additional work. Plus, many of my scripts are based around an idea I have, and a desire to figure out how to do it natively in PowerShell.
Plus – 2003? Really? That’s getting pretty outdated.