Logging output of user disable and group removal - Powershell no Quest - powershell

I have some existing code that I've pieced together from my google searches.
Hi All,
I spent some time googling to find the code needed and this is what I have below.
What I'm wanting to do is log the groups being removed from a user either.
a) Into a local text (.log) file
or
b) Into the users "Notes" field.
I've found code on how to do logging if I use quest addin, but cannot fathom how to make it fit WITHOUT using quest.
Doing this as a learning + work functional task to make it speedier to disable users.
Import-Module activedirectory -ErrorAction silentlycontinue
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin -ErrorAction silentlycontinue
$username = read-host "Username"
$users= get-aduser $username
Function RemoveMemberships
{
param([string]$SAMAccountName)
$user = Get-ADUser $SAMAccountName -properties memberof
$userGroups | %{get-adgroup $_ | Remove-ADGroupMember -confirm:$false -member $SAMAccountName}
$userGroups | %{get-adgroup $_ | Remove-ADGroupMember -confirm:$false -member $SAMAccountName} $userGroups = $user.memberof
$userGroups = $null
}
$users | %{RemoveMemberships $_.SAMAccountName}
Move-ADObject $users -TargetPath "OU=Disabled Users,DC=contoso,DC=com" -PassThru | Disable-ADAccount
edit: The inclusion of the Exchange PSSnapin is for enhancing with disabling on GAL. I have code, but didn't include it in this.

A simple on-screen answer using Write-Host
$userGroups | %{Write-Host "Removing user from group $_"; get-adgroup $_ | Remove-ADGroupMember -confirm:$false -member $SAMAccountName}

Related

Powershell Script to get all groups containing specific name

Okay, so I am a little new to powershell and I am trying the best I can but cannot seem to get this.
The way my directory is setup is that each organization has their own "Password Reset Group" I will have a scheduled task setup that runs based on the event log entry "Directory Service Change". The script's job is to find members in the groups and reset their password back to their employeeNumber, make the user change the password at next logon and then remove the user from the group. I seem to be having issues getting the syntax correct.
Try {
$GroupDN = (Get-ADGroup -Filter {Name -like '*Password Reset Group*'}).DistinguishedName
}
Catch {
Write-Host "Unable to locate group: $Group because ""$($Error[0])""" -ForegroundColor Red
Exit
}
ForEach ($User in (Get-ADUser -Filter * -Properties MemberOf,employeeNumber))
{ If ($User.MemberOf -contains $GroupDN)
{ $password = "$($_.employeeNumber)new!" | ConvertTo-SecureString -AsPlainText -Force
Set-ADAccountPassword -Identity $User -NewPassword $password -Reset
Remove-ADGroupMember -Identity "$GroupDN" -Members $User
}
}
Good to see you came up with your own answer, but you can simplify this by just using ...
Get-ADPrincipalGroupMembership
# get function / cmdlet details
(Get-Command -Name Get-ADPrincipalGroupMembership ).Parameters
Get-help -Name Get-ADPrincipalGroupMembership -Full
Get-help -Name Get-ADPrincipalGroupMembership -Online
Get-help -Name Get-ADPrincipalGroupMembership -Examples
# Example 2: Get group memberships for the Administrator
Get-ADPrincipalGroupMembership -Identity Administrator
... which lists all the groups a user belongs to.
So, your adjustment could be just this...
Get-ADUser -Filter * |
ForEach{
# "`n--- Processing user $($PSItem.SamAccountName) ---`n"
If ($TargetGroup = (Get-ADPrincipalGroupMembership -Identity $PSItem.SamAccountName) -match 'Password Reset Group')
{
$password = "$($PSItem.employeeNumber)new!" |
ConvertTo-SecureString -AsPlainText -Force
Set-ADAccountPassword -Identity $PSItem.SamAccountName -NewPassword $password -Reset
Remove-ADGroupMember -Identity $TargetGroup.SamAccountName -Members $PSItem.SameAccountName
}
}
As for …
Okay, so I am a little new to powershell
… that is all well a good, but it is prudent for you to spend the time getting ramped up on PowerShell to limit / avoid guessing, misconception, frustration, bad habits, errors, etc., that you are going to continue to encounter (even the most experienced of us do and learn from it and each other). There are tons of no cost / free resources all over the we for you to leverage.
Live on YouTube, MVA, MSDN Channel9 for all the video training.
Use tools that will write the code for you, that you can save and tweak as needed later. Especially when it comes to ADDS.
Active Directory Administrative Center: Getting Started
Active Directory Administrative Center
Step-By-Step: Utilizing PowerShell History Viewer in Windows Server 2012 R2
Free Books and references
Using the information given to me by #AdminOfThings. I was able to write the code I wanted. It took a lot of playing around but here it is:
ForEach ($GroupDN in (Get-ADGroup -Filter {Name -like '*Password Reset Group*'}).DistinguishedName)
{ ForEach ($User in (Get-ADUser -Filter * -Properties MemberOf,employeeNumber))
{ If ($User.MemberOf -contains $GroupDN)
{ $password = $User.employeeNumber | ConvertTo-SecureString -AsPlainText -Force
Set-ADAccountPassword -Identity $User -NewPassword $password -Reset
Set-ADUser -Identity $User -ChangePasswordAtLogon $true -PasswordNeverExpires $false
Remove-ADGroupMember -Identity "$GroupDN" -Members $User -Confirm:$false
}
}
}

PowerShell script runs with error first time, but correctly second or third time

I have a script to disable users in AD with the following steps:
asks for username
set "domain users" group as primary group
disable users in AD
move to disabled OU
clear Manager from AD
remove all groups except 'domain users'
Add disabled_mailboxes to the user
Hide account from exchande list
Now, when i try the first time it does not work. i have to run it several times like 2 3 and 4 times to work.
When i run it step by step, it work fine also from the first time
and here is the script:
$username = Read-Host -Prompt 'Enter Username'
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
Import-Module ActiveDirectory
$user = Get-ADUser -Filter {(SamAccountName -eq $username)} -Properties MemberOf
#set "domain users" group as primary group
$group = get-adgroup "Domain Users" -properties #("primaryGroupToken")
get-aduser $username | set-aduser -replace #{primaryGroupID=$group.primaryGroupToken}
#disable users in AD
Get-ADUser -Filter {(SamAccountName -eq $username)} | Disable-ADAccount -ErrorAction SilentlyContinue
#move to disabled OU
Get-ADUser -Filter {(SamAccountName -eq $username)} | Move-ADObject –TargetPath “OU=Users,OU=Disabled Objects,DC=xxxxxxx,DC=xxx,DC=XXX”
#clear Manager from AD
Get-ADUser -Filter {(SamAccountName -eq $username)} | Set-ADUser -Clear manager
#-------------------------
#remove all groups except 'domain users'
Get-ADPrincipalGroupMembership -Identity $username | % {Remove-ADPrincipalGroupMembership -Identity $username -MemberOf $_ -Confirm:$false -ErrorAction SilentlyContinue}
#code can be removed.
#$group = $user | Select-Object -ExpandProperty MemberOf
#Remove-ADGroupMember -Identity $group -Members $user.SamAccountName -Confirm:$false -ErrorAction SilentlyContinue
#-------------------------
#Add disabled_mailboxes to the user
Add-ADGroupMember -Identity 'disabled_mailboxes' -Member $User.SamAccountName -ErrorAction SilentlyContinue
#-------------------------
#Hide account from exchande list
Set-Mailbox -identity $user.SamAccountName -HiddenFromAddressListsEnabled $true -ErrorAction SilentlyContinue
Windows 2012R2, Exchange 2010
Can anyone help with that???
Thanks
Mina
Do not use Get-ADUser repeatedly in the sequential lines. Just use the existing $user variable that you've just populated with values. Most likely you are hitting an issue that Get-ADUser returns old cached value for DN right after you run Move-ADObject (this changes the DN of the user), and since all queries use DN to locate the user, you get the error. The second run has the target user already in the destination OU, so no errors arise.

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 - printing out during a loop

I have to go through an OU and remove all the memberOf groups for all users. The script I have works, but I cannot get it to print out when each user is processed. So when I run the script, it working, but nothing happens until its complete. For piece of mind, I want to SEE the current login name that is being processed, but I can't, for the life of me, get the write-host command to write to my screen.
Here is my code:
$users = get-aduser -filter * -searchbase "ou=disabled,dc=corp,dc=test,dc=org" | Sort-Object -Property Name
Function removeMemberShips {
Param( [string] $SAMAccountName)
$user = get-aduser $SAMAccountName -properties memberof
$userGroups = $user.memberof
$userGroups | %{get-adgroup $_ | Remove-ADGroupMember -confirm:$false -member $SAMAccountName}
$userGroups = $null
}
$users | %{removeMemberShips $_.SAMAccountName}
The most obvious way seems to be:
$users | %{
removeMemberShips $_.SAMAccountName
Write-Host $_.SAMAccountName
}