longer execution time after Get-ADUser when a server is specified - powershell

I have a script that queries AD and processes the result:
$users=Get-ADUser -filter {...} -Properties ...
try {
foreach($user in $users) {
$obj=new-object PSObject #property {...}
[void]($arraylist.add($obj))
}
}
catch {...}
the Get-ADUser takes about 1.5sec and returns 1000+ rows, and the whole try block takes about 0.5sec.
the #Properties {...} part only processes $user fields and has no further interaction with the AD or any other resource. the try block runs without error.
if now I change the first line to
$users=Get-ADUser -filter {...} -Properties ... -Server <someDC>
just adding a -Server parameter, the Get-ADUsercommand takes about 3sec and the try block 20+sec
I tried many times to be sure that the remote connection is well established without any improvement. I tried with each of the available DCs and got the very same execution time each time. If I remove the -Server parameter, I get the original execution time back.
the problem has similarities with the one described in this post but the my problem is with the code executed after the Get-ADUser, not with the Get-ADUser by itself.
what is very disturbing is that it's the code after which get slower.
do you have any clue?
DC: Win2008R2
Client: Win7, Powershell5.1, AD Management Tools locally installed.

Related

Add AD user to group when creating the user?

I've seen multiple examples on adding a user to a group after creation, but not at the time of creation. Is that possible? Currently, I have something like this: (most attributes removed for simplicity)
$user = New-ADUser -Name "person" -Path "OU=test,OU=myorg" -Office "home" -samAccountName "snuffy.john" -PassThru
if ($user){
Add-ADGroupMember -Identity mygroup -Members $user.samAccountName
}
This causes two calls to the ldap server for each user added and I'm trying to prevent that as I have many thousands of users and the script takes a long time to run. I've checked MS docs but didn't see anything. If it's not possible, it is what it is. Thought I'd try asking at least. I also just started using powershell last week.
You may turn your thinking. with thousands of users I would do it like this.
First create all users.
Then get them by Get-ADUser -Filter * -SearchBase "OU=test,OU=myorg" (or maybe Filter the CreatedDate Attribute to get all new users)
After getting the users try to filter them for the groups you want to put them into and use the Add-ADGroupMember cmdlet, which accepts an array of ADPrincipals for parameter "-members".
This will speed up your code.

How to extract a list of users with rights to create domain users in the Active Directory?

I was tasked with creating Powershell scripts that we will use to review the Active Directory of our clients. I like to add that my knowledge of Powershell is very basic, but I've found A LOT online (including many Stack Overflow topics!) to help me with this task. My script is pretty much in place, but there is one functionality that I would like to add to my script. I do not know if (and how) this even possible. I've looked at many sites to help me with this issue, but I did not find any solutions. So I decided to ask it to the community itself. Here is a description of my issue.
What I want is to have a list of users that have the rights to create Domain Users and have the rights to install Updates / Hot-Fixes on Domain Controllers. In order to be able to create a Domain User, the user must have a membership (or equivalent) to Domain Administrators (Found here https://technet.microsoft.com/en-us/library/dd894463(v=ws.10).aspx. It's easy to get the Domain Administrators and Enterprise Administrators (the latter having also the ability to create Domain Users obviously). I have a script that retrieves all the Domain Users and the groups that they have membership to, so that is covered.
What I want to achieve is to get Domain Users that are not a member of the Domain Administrators (or equivalent) groups that have rights to create Domain Users (or within certain OU's like explained in this topic https://serverfault.com/questions/83686/how-to-create-a-limited-domain-admin-that-does-not-have-access-to-domain-contr).
There is not an attribute that defines what I am looking for. I had some ideas of using de 'admincount' property like this: Get-ADUser -Server $ADServer -Filter {admincount -gt 0}. This returns to me all the ADUsers that are within the Default Protected Groups within the Active Directory. But what I want is to be able to get Users that are not contained in these groups.
Is there a way to get this information?
Sorry I began fully coding this but without seeing your script and not having a full test AD env in front of me at the moment, I will give you the psudo-code as it seems like you've done enough that you can probably take this code and run with it and pretty easily have a fully working script since most the primary commands/filters needed I have included below:
Get a list of all OUs
$OUs = #(Get-ADDomain | Select-Object -ExpandProperty DistinguishedName)
$OUs += Get-ADOrganizationalUnit -Filter * | Select-Object -ExpandProperty DistinguishedName
$OUs += Get-ADObject -SearchBase (Get-ADDomain).DistinguishedName -SearchScope OneLevel -LDAPFilter '(objectClass=container)' | Select-Object -ExpandProperty DistinguishedName
Get a filtered list of all non-admin users using:
Get-ADUser -Server $ADServer -Filter { admincount -eq 0 }
Loop through each of the OUs and retrieve their permissions
foreach ($OU in $OUs)
(Get-Acl $OU).access | where { accesscontroltype -eq 'Allow' })
Inner loop your filtered non-admin user array with each access permission needed to perform the pseudo-admin duties using:
foreach ($objUser in $(Get-ADUser -Server $ADServer -Filter { admincount -eq 0 }))
(Get-Acl $OU).access | where { identityreference -eq <TRIMMED INNER LOOP USER OBJECT NAME FROM $objUser> }
If matched, add to new array, otherwise do nothing
Dump array to report

The server has returned the following error: invalid enumeration context

When I run First part it works fine, however, the Second option (which I want to use) does not work and is giving me an error:
Error getting objects: The server has returned the following error:
invalid enumeration context
I Tried following this article.
I tried result page size with different values but it does not work either. I checked the second Cmdlet with Measure-Command and it is taking 17 minutes to fetch AD objects and time out time is mentioned in the ADWS server is 30 minutes.
Could you please help me to understand what is wrong? We do not want to user the first option; we want to import all account irrespective date and time.
I want to remove date filter which I am using in the first option and wanted to to get ad object in a script without mentioning days and should fetch all records old and the new one. Please help experts here :)
First
$from = ((Get-Date).AddDays(-100)).date
$to = ((Get-Date).AddDays(0)).date
$A = #(Get-ADUser -Filter { whenCreated -ge $from -and whenCreated -le $to } -Properties * -Server $DomainController)
Second
$A = #(Get-ADUser -Filter '*' -Properties * -Server $DomainController)

Finding a User on one of many domains

I am trying to get a script running but I keep running across the same issue, I have domains A, B, and C all in the same forest; but when I try to do simple commands such as
Disable-ADAccount -Identity $User
I am not able to get it to complete because it can't find the user in Domain B, which the user is in Domain A.
So the question, is there a way to get a script to check all domains (A, B, C) for "User1" and preform the disable action on them. (Other than setting the Switch)
-server
I ran into this issue recently, and ended up writing a function to get a user's ADUser object. You could use that object to disable the user easily enough.
Function Get-DomainUser{
Param([String]$Alias)
BEGIN{$GCs = Get-ADForest|select -expand GlobalCatalogs|?{($_ -match "^(.*?)\.(.+?)$")}|%{[pscustomobject]#{'Server' = $matches[1];'Region' = $matches[2];'FQDN' = $_}}|group region|%{$_.group|select -first 1}
}
PROCESS{
$DomUser = Get-ADUser -Filter {samAccountName -eq $Alias} -Prop DisplayName
If(([string]::IsNullOrEmpty($DomUser.Name))){
ForEach($GC in $GCs){
$DomUser = Get-ADUser -Filter {samAccountName -eq $Alias} -Server $GC.FQDN -Prop DisplayName
If(!([string]::IsNullOrEmpty($DomUser.Name))){Break}
}
}
$DomUser
}
}
This gets a list of global catalog servers, groups them by sites, then gets only 1 server per site. Then it tries to get the user, and if it fails for the current user then it tries each site until it finds the user.

Detect null object in powershell:

I am working on implementing some user creation in active directory using the built in powershell commandlets, recently I came across this issue. When attempting to read in a data file of users where $_.UID is one of the fields in the file, I do a Get-ADUser with the UID to check if the user already exists in ldap. If I get a null object, then I would like to create the user because this id is not already in ldap otherwise I would like to skip the entry in the datafile. My script as is creates the users the first time through. If I run it a second time on the same data file (users should no longer be null for the UID field) the if condition is still true and the script attempts to create users a second time. I am new to powershell scripting so I must be misunderstanding something. What am I doing wrong? Your help is appreciated!
Function createUsers{
Import-CSV "~\Desktop\inData.csv" | ForEach-Object {
$USER = Get-ADUser -LDAPFilter "(uid=$_.UID)"
if($USER -eq $Null){ #BROKEN DOESN'T DO ANYTHING
#(!$USER) Doesn't work either
Write-Host "Making next user."
.
.
.
}else{
Write-Host "Skipping, user exists!!"
}
}
}
I think that your problem is in your Get-ADUser Query. There is no property called "uid" in Active Directory. This will make $USER always null, and cause it to always want to create a new user.
Try using sAMAccountName instead:
$User = Get-ADUser -LDAPFilter "(sAMAccountName=$_.UID)"
To get a full list of all the properties available to you, I like to execute the following:
Get-ADUser MyUserName -Properties *