How can I clone a GroupOfNames Active Directory Object? - powershell

I'm writing a script to take one GroupOfNames object and create a second group with the first groups members. It seems like it would be a very simple piece of code:
$obj = Get-ADObject -Server "$server" -SearchBase $SearchBase -Filter "name -eq '$GroupName'" -Properties Member
New-ADObject -Server "$server" -Path $SearchBase -Type 'GroupOfNames' -name "$NewGroupName" -OtherAttributes #{'Member'= ($($obj.Member))}
When I run this the $obj gets created and I can display both the GroupOfNames information, as well as the list of members. But when it calls the New-ADObject cmdlet, I get the following error:
New-ADObject : Unable to contact the server. This may be because this server does not exist, it is currently down, or it does not have the Active Directory Web Services running.
I've tried multiple variations of the code and all fail with similar errors.
Interestingly, if I loop through the list of members and add them to the group one at a time, it works, but it just takes way too long (an hour+ vs seconds).

Try this, it casts the results of your first query, ADPropertyValueCollection, to a string array(untested!):
$obj = Get-ADObject -Server "$server" -SearchBase $SearchBase
-Filter "name -eq '$GroupName'" -Properties Member
$m = [string[]]$obj.Member
New-ADObject -Server "$server" -Path $SearchBase -Type 'GroupOfNames'
-name "$NewGroupName" -OtherAttributes #{'Member'= $m}

After some trial and error, I found that I could reliably add about 6000 members at a time. Here's the basic flow:
(Get-ADObject -Server "$server" -SearchBase $SearchBase -Filter { name -eq "$GroupName" } -Properties Member).Member | %{
$SubList += [string] $_
if($SubList.count -ge 6000) {
Set-ADObject -Server "$server" -Identity $NewGroup -Add #{'Member'= ($SubList)}
$SubList = #()
}
}
if($SubList.count -gt 0) {
Set-ADObject -Server "$server" -Identity $NewGroup -Add #{'Member'= ($SubList)}
}
Thank you #Raf for the push in the right direction.

Related

Renaming AD user object name in powershell

I am trying to get only AD Objects of type user and then iterate over all them and change AD user object name. So I have done below:
$Users = Get-ADObject -Filter {(ObjectClass -eq "user")} # OR Get-ADObject -Filter 'ObjectClass -eq "user"'
$Users | foreach
{
# Here code to create name based on conditions ($newUserObjectName)
Rename-ADObject -Identity $_ -NewName $newUserObjectName
}
The problem is that Get-ADObject is returning not only users but also computer objects.... I only want user object classes. Also I am not sure If below line of code is correct by setting identity to $_ in order to update the current user in the iteration:
Rename-ADObject -Identity $_ -NewName $newUserObjectName
Why not use Get-ADUser instead of Get-ADObject and just return the DistinguishedName? Obviously, DON'T just run this code :)
$users = (Get-ADUser -Filter *).DistinguishedName #This gets all the users in AD
Foreach($user in $users){
Rename-ADObject -Identity $user -NewName $newUserObjectName
}
The Computer objectClass is derived from the User objectClass. Hence, queries for user class will return both Computers and Users. If you want to filter for Users only, you have to specify ObjectCategory as Person
$Users = Get-ADObject -Filter {(Objectclass -eq "user") -and (objectCategory -eq "Person")}
Use that or you can use the goodole Get-ADuser
Use Get-ADUser and Set-ADUser:
$Users = Get-ADUser -Filter *
$Users | foreach {
# Naming code
Set-ADUser -Identity $_.SamAccountName -SamAccountName $newName
}
This replaces all user's identities to $newName.
Note you can replace -SamAccountName with any other property of an ADUser. for example if you want to replace the display name instead, you would use -Name $newName

Powershell - How can I test the result of my command?

Sorry for this stupid question but I don't know how to simply test the result of my command (it returns an object)!
Here is my command:
$command = Get-ADUser -Server "MyServer" -Filter 'Name -eq "test"' -SearchBase "DC=MyDomain,DC=COM" -Properties badpwdcount,lockedout | Select-Object LockedOut
I just want to test the result like this :
if($command -eq $true){
write-host "OK"
}
When I try this command to see the result :
write-host $command
I get "#{LockedOut=True}". So, I have tried to change also my condition like :
if($command -eq "#{LockedOut=True}"){
write-host "OK"
}
But it's not working...
When Write-Host $command outputs #{LockedOut=True}, it's because Select-Object LockedOut produces a new object with a LockedOut property.
Either change your Select-Object statement to use the -ExpandProperty parameter:
$command = Get-ADUser -Server "MyServer" -Filter 'Name -eq "test"' -SearchBase "DC=MyDomain,DC=COM" -Properties badpwdcount,lockedout | Select-Object -ExpandProperty LockedOut
if($command){
# "test" user is locked out
}
or inspect the LockedOut property:
if($command.LockedOut){
# "test" user is locked out
}
As you can see, the -eq $true comparison inside an if statement is redundant
Be aware that you may get unexpected results if you have multiple users with the name test in your directory. If you're locating users by username, you should filter on the SAMAccountName property (which is guaranteed to be unique per-domain):
$command = Get-ADUser -Server "MyServer" -Filter 'SAMAccountName -eq "test"' -SearchBase "DC=MyDomain,DC=COM" -Properties badpwdcount,lockedout | Select-Object -ExpandProperty LockedOut
if($command){
# "test" user is locked out
}

Powershell Shadow Groups - Inconsistent Group Membership

I am using Powershell to maintain several shadow groups (a group that mirrors all the users in a specific OU.)
I have three OUs, Staff, Faculty, and Administration. Each has a group associated with it, with the Staff group encompassing all three groups.
Here is the code:
$server="win-ad1.example.com"
#Staff
$AdministrationOU="OU=Administration,OU=Accounts,DC=example,DC=com"
$FacultyOU="OU=Faculty,OU=Accounts,DC=example,DC=com"
$StaffOU="OU=Staff,OU=Accounts,DC=example,DC=com"
$ShadowGroup="CN=Staff,OU=User Groups,OU=Accounts,DC=example,DC=com"
Get-ADGroupMember -Server $server –Identity $ShadowGroup `
| Where-Object {($_.distinguishedName –NotMatch $AdministrationOU) `
-OR ($_.distinguishedName –NotMatch $FacultyOU) `
-OR ($_.distinguishedName –NotMatch $StaffOU)} `
| ForEach-Object {Remove-ADPrincipalGroupMembership -Server $server –Identity $_ –MemberOf $ShadowGroup –Confirm:$false}
Sleep -Seconds 2
Get-ADUser -Server $server –SearchBase $AdministrationOU –SearchScope OneLevel –LDAPFilter "(!(memberOf=$ShadowGroup))" `
| ForEach-Object {Add-ADPrincipalGroupMembership -Server $server –Identity $_ –MemberOf $ShadowGroup}
Get-ADUser -Server $server –SearchBase $FacultyOU –SearchScope OneLevel –LDAPFilter "(!(memberOf=$ShadowGroup))" `
| ForEach-Object {Add-ADPrincipalGroupMembership -Server $server –Identity $_ –MemberOf $ShadowGroup}
Get-ADUser -Server $server –SearchBase $StaffOU –SearchScope OneLevel –LDAPFilter "(!(memberOf=$ShadowGroup))" `
| ForEach-Object {Add-ADPrincipalGroupMembership -Server $server –Identity $_ –MemberOf $ShadowGroup}
#Administration
$ShadowGroup="CN=Administration,OU=User Groups,OU=Accounts,DC=example,DC=com"
Get-ADGroupMember -Server $server –Identity $ShadowGroup `
| Where-Object {$_.distinguishedName –NotMatch $AdministrationOU} `
| ForEach-Object {Remove-ADPrincipalGroupMembership -Server $server –Identity $_ –MemberOf $ShadowGroup –Confirm:$false}
Sleep -Seconds 2
Get-ADUser -Server $server –SearchBase $AdministrationOU –SearchScope OneLevel –LDAPFilter "(!(memberOf=$ShadowGroup))" `
| ForEach-Object {Add-ADPrincipalGroupMembership -Server $server –Identity $_ –MemberOf $ShadowGroup}
Get-ADGroupMember -Server $server –Identity $ShadowGroup `
| Enable-ADAccount -Server $server
....
#same code for Faculty
This is (I think) pretty standard code, but I admit to writing very little powershell. The code should remove all the users in the group that aren't in the OU, then add all the users (not already in the group) that are in the OU to the group.
In theory, this works great, however in practice adding/removing users to the Staff group can go massively wrong. In one run of the script, it will suddenly remove swathes of (random) users from the group, despite them obviously being in one of the OUs. A run of the script again may add them back or take out other users. Many time the script runs perfectly.
I had initially chalked it up to the script talking to different domain controllers, so I added the -Server argument to each Active Directory call, so that it would hit the same (primary) domain controller each time. The problem still occurs, and in all of my searching I can't find anyone with the same issue (probably because I'm not really sure how to phrase what is happening.)
Any help would be appreciated.
Note, for scale here are the size of the OUs:
Staff: 199
Faculty: 194
Administration: 32

Powershell Adding users within groups to cross forest groups

This script works without error now, but the problem is that when several groups in the searchbase are found, the script will add all users from all groups to the cross forest target groups.
So for example:
ForestAGroup1 = contains 2 users
ForestAGroup2 = contains 2 users
::runs script::
now...
ForestBGroup1 = contains 4 users
ForestBGroup2 = contains 4 users
The ForestBGroup1/2 needs to contain the same identical users as ForestAGroup1/2.
Here is the script for reference:
$creds = Get-Credential
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domainA,DC=com" | export-csv c:\temp\test.csv
$Groups = Get-ADGroup -Properties * -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domainA,DC=com"
Foreach($G In $Groups)
{
#Display group members and group name
Write-Host $G.Name
Write-Host "-------------"
$G.Members
#Add members to domainB group
$domainGMembers = import-csv C:\temp\test.csv | ForEach-Object -Process {Get-ADGroupMember -Identity $_.CN} | Select-Object samaccountname | export-csv c:\temp\gmembers.csv
$domainDNUser = import-csv C:\temp\gmembers.csv | ForEach-Object -Process {Get-ADUser $_.samaccountname -Server "domainA.com" -properties:Distinguishedname}
import-csv C:\temp\gmembers.csv | ForEach-Object -Process {Add-ADGroupMember -Server "domainB.com" -Identity $G.Name -Members $domainDNUser -Credential $creds -Verbose}
}
What are you doing?
You export to csv, but still try to save it to a variable
You search twice
You add all members from ALL groups in TEST-OU to every group in domainB
You waste time on saving and reading data that you already have in memory
You search for the user-object to get SamAccountName when you already have something ten times better, the DN. Then you use that SamAccountName to find the DN.
Try this (untested):
$creds = Get-Credential
$Groups = Get-ADGroup -Properties Members -Filter * -SearchBase "OU=TEST,OU=Shop Print Groups,OU=User,OU=domain Groups,DC=domain,DC=com"
Foreach($G In $Groups)
{
#Display group members and group name
Write-Host $G.Name
Write-Host "-------------"
$G.Members
#Add members to domainB group
$G.Members |
Get-ADUser -Server fairfieldmfg.com |
ForEach-Object { Add-ADGroupMember -Server "domainB.com" -Identity $G.Name -Members $_ -Credential $creds -Verbose }
}
I used a foreach-loop to run the Add-ADGroupMember because it usually fails in the middle of a group of members if it finds on the already is a member, but if we add them one at a time you get around that (or you could do a search and exclude those already in the group).
You may want to add -ErrorAction SilentlyContinue to Add-ADGroupMember to ignore those errors when you know the script works as it should.

Powershell set-adcomputer issue set location

I have made this script to set/change the location attribute of computers in a specific OU.
My variable is ok but when I execute, it is not taking it line by line.
How can I solve this.
Import-module ActiveDirectory
$computers= Get-ADcomputer -Filter * -searchbase "OU=XX,OU=XXX,OU=WXXX,DC=TGE,DC=XX,DC=XX" | ForEach-Object {$_.Name}
Set-ADcomputer -identity "$computers" -Location "buildingA"
Your $Computers is an [Array] Object which means it has a set of objects inside
The Set-ADComputer command cannot process all the array at once, to process each one of them you need to use the 'Foreach' method for example:
Foreach ($Computer in $Computers)
{
Set-ADcomputer -identity $computer -Location "buildingA"
}
Another Approach is add the foreach after the pipe, like this:
Get-ADcomputer -Filter * -searchbase "OU=XX,OU=XXX,OU=WXXX,DC=TGE,DC=XX,DC=XX" | ForEach-Object {Set-ADComputer -identity $_ -Location "buildingA"}
Try piping the output of Get-ADcomputer into Set-ADcomputer:
Get-ADcomputer -Filter * -searchbase "OU=XX,OU=XXX,OU=WXXX,DC=TGE" | Set-ADcomputer -Location "buildingA"