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:
$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, Skype for Business MVP
Email/Blog/Twitter : pat@innervation.com https://www.ucunleashed.com @patrichard
Dedicated Post : https://www.ucunleashed.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
Function: Set-AdminUser – Clear AdminCount and Enable Security Inheritance
.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
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