Skip to content

Instantly share code, notes, and snippets.

@phyoewaipaing
Last active September 1, 2023 12:58
Show Gist options
  • Save phyoewaipaing/a454e5ceaee302702331d5c40c5140f9 to your computer and use it in GitHub Desktop.
Save phyoewaipaing/a454e5ceaee302702331d5c40c5140f9 to your computer and use it in GitHub Desktop.
The script that will help you complete the day-to-day AD operations quite easy
##################################################################################################################################################################################################################################################################################
## This script will do the common AD operations the system admin is supposed to do. Active Directory powershell module is needed for this script to run.
## The parameters to run the script are explained as follows:
## -Operation : The AD operation that you want to perform on users or groups. The available operations must be one of the following:
## GetUsersAttribute : Get the required attributes of the users (defined in Text file or as OU DistinguishedName) and save to the csv file. Please note that you have to enter the attribute names (as you see in the Attribute Editor Tab of dsa.msc) and press Enter
## GetUsersFromGroups : Get all users from the specific groups (defined in Text file or as OU DistinguishedName) and save the result to the 'Members Of <groupname>.txt' file. You need to use the -TxtFilePath or -OUDistinguishedName
## GetGroupsFromUsers : Get the groups of the users (defined in Text file or as OU DistinguishedName), and separated by commas and save into the file 'AD_Users_and_Groups_Info.csv'
## AddUsersToGroup : Add users (defined in Text file or as OU DistinguishedName) into the specific group (defined as -GroupName)
## RemoveUsersFromGroup : Remove users (defined in Text file or as OU DistinguishedName) from the specific group (defined as -GroupName)
## EnableUsers : Enable users (defined in Text file or as OU DistinguishedName)
## DisableUsers : Disable users (defined in Text file or as OU DistinguishedName)
## DeleteUsers : Delete users (defined in Text file or as OU DistinguishedName)
## ResetPasswordTimeStamp : Reset the password timestamp of users (so that users password expiration is extended for a next period eg: 3 months as defined by AD policy)
## ResetPassword : Reset users' password. You need to defind the password string with -PasswordString in quotes.
## SetAccountExpiryDate : Set the account expiry date of user accounts. The date should be given as MM/dd/yyyy.
##
## -TxtFilePath : The text file of user or group names. The selected operations will be performed on these users or groups.
## -GroupName : The group name which will be used for group membership add or remove operations against the users specified.
## -OUDistinguishedName : The OU path under which all users or groups will be used for further processing (the purpose is same as the -TxtFilePath). Please note that all child users or groups will be affected.
## -PasswordString : The password string which will be used for the password reset operation (when you use -Operation ResetPassword)
## -AccountExpiryDate : The datestamp which will be used to set the account expiry date. Value should be given as MM/dd/yyyy format
##
## Author : Phyoe Wai Paing
## Country : Myanmar(Burma)
## Website : https://www.scriptinghouse.com
## Version : 1.0 : 16.Apr.2023 : Initial Release
#################################################################################################################################################################################################################################################################################
param ([ValidateSet("GetUsersAttribute","GetUsersFromGroups","GetGroupsFromUsers","AddUsersToGroup", "RemoveUsersFromGroup", "EnableUsers","DisableUsers", "DeleteUsers","ResetPassword","ResetPasswordTimeStamp","SetAccountExpiryDate")][string]$Operation,[ValidateNotNullOrEmpty()][string]$TxtFilePath,[ValidateNotNullOrEmpty()][string]$GroupName,[ValidateNotNullOrEmpty()][string]$OUDistinguishedName,[ValidateNotNullOrEmpty()][String]$PasswordString,[ValidateNotNullOrEmpty()][String]$AccountExpiryDate)
## If the TxtFilePath is found, then just fetch the user info ##
If (!([string]::IsNullOrWhiteSpace($TxtFilePath)))
{
$UserOrGroupNames = Get-Content -Path $TxtFilePath
$UserOrGroupNamesInfo = $UserOrGroupNames | ? { !([string]::IsNullOrWhiteSpace($_)) } | % {
$CurSamAccountName = $_.Trim();
Try {
If ($Operation -eq 'GetUsersFromGroups')
{
Get-ADGroup -identity $CurSamAccountName
}
else
{
Get-ADUser -identity $CurSamAccountName -Properties GivenName,SurName,SamAccountName,MemberOf,Description,Title,Enabled,PasswordExpired,PasswordLastSet,AccountExpirationDate -EA Stop
}
}
catch {
Write-Host -fore yellow "[Warning]: Cannot find the user : $CurSamAccountName"
}
}
## Re-insert the found SamAccountNames to the variable for further subsequent actions ##
$UserOrGroupNames = $UserOrGroupNamesInfo.SamAccountName
}
## Check if the OU DN / Txt File Path is present or not and process accordingly ##
elseIf (!([string]::IsNullOrWhiteSpace($OUDistinguishedName)))
{
Try {
## Get the users or groups under the OU based on the parameter inputted ##
If ($Operation -eq 'GetUsersFromGroups')
{
$UserOrGroupNamesInfo = Get-ADGroup -Filter * -SearchBase $OUDistinguishedName
$UserOrGroupNames = $UserOrGroupNamesInfo.Name
}
else
{
$UserOrGroupNamesInfo = Get-ADUser -Filter * -SearchBase $OUDistinguishedName -Properties GivenName,SurName,SamAccountName,MemberOf,Description,Title,Enabled,PasswordExpired,PasswordLastSet,AccountExpirationDate
$UserOrGroupNames = $UserOrGroupNamesInfo.SamAccountName
}
}
catch {
Write-Host -fore red "[Error]: The following OU is not found. Make sure you entered it correctly as the distinguished name with the quotes."
Write-Host $OUDistinguishedName;
}
}
Else #([string]::IsNullOrWhiteSpace($TxtFilePath))
{
Write-Host -fore red "[Error]: You need to specify the -TxtFilePath with SamAccountNames or -OUDistinguishedName with the distinguished name of OU to pick up users from. Script exits."
EXIT;
}
########### Give Warning to users ##########
## Function to give the user warning if the write-operation parameters are used ##
Function Prompt_User
{
param( [string]$QuestionString,[System.Array]$UserOrGroupNamesInfo )
## Prompt for confirmation if it's a write operation ##
$UserOrGroupNamesInfo | select GivenName,SurName,SamAccountName,Enabled,@{N='PwdExpired';Exp={$_.PasswordExpired}},PasswordLastSet,@{N='AccExpiryDate';Exp={ If (!($_.AccountExpirationDate)) { 'Never' } else {$_.AccountExpirationDate}}},Description,Title | ft -auto
$Ans = Read-Host "$QuestionString Do you want to continue?(y/n)"
If($Ans -ne 'y')
{
Write-Host "`'y`' is not entered. Script exists";
EXIT;
}
}
$EffectiveCount = 0; ## Initially set the count to zero
$i = 0;
$Ans = 1; ## Initially set the Ans to non-zero
switch($Operation)
{
"GetUsersAttribute" {
If ($UserOrGroupNames.Count)
{
$AttribArray = @();
while ($Ans -ne 0)
{
$Ans = Read-Host "Please input the AD Attribute Name and press Enter (Press 0 to stop prompting)."
If ($Ans -match '[!@#$%^&,\(\)\{\}\[\]*?<>= ]')
{
Write-Host -fore yellow "Your input cannot contain comma, space, quotes, brackets or special characters.`n"
Continue;
}
elseIf ($Ans -eq 0 -AND $i -eq 0)
{
Write-Host "0 is pressed. Script exits."
EXIT;
}
else
{
$AttribArray += $Ans | ? { $_ -ne 0 } | % { $_.Trim() };
}
$i++;
}
Write-Host "Please wait..." -NoNewLine
## By using the variable which contains the attributes, we expand the select statment (it's because some attributes need to use -join in the select statement, otherwise the output csv file output will contains "Microsoft.ActiveDirectory.Management.ADPropertyValueCollection") ##
$SelectStringWithFirstComma = ($AttribArray | % { ",@{N=`'$_`';Exp={`$_.$_ -join ''}}" }) -join ''
$SelectString = $SelectStringWithFirstComma.Remove(0,1) ## Remove the first comma which was concatenated by the above statement
## Get the AD users' attributes based on the select string (which is constructed by the user's inputted sequence of attributes ##
$UserOrGroupNames | % {
Try {
$CurUserorGroup = $_;
Get-ADUser -identity $CurUserorGroup -Properties $AttribArray -EA Stop -EV Err | Select $(Invoke-Expression -Command $($SelectString.tostring()))
}
catch [System.ArgumentException]{
$InvalidParameter = $Err.Message | out-string | % { ($_ | findstr "Parameter name:") -replace "Parameter name: ","" }
Write-Host -fore red "`r$CurUserorGroup : One or more parameters are invalid : $InvalidParameter"
}
} | Export-Csv -notype AD_Users_Attrib_Info.csv
## Output the message if there is no error ##
If (!$Err)
{
Write-Host -fore green "`rThe attributes of users: $($AttribArray -join ',' ) are fetched and saved to AD_Users_Attrib_Info.csv."
}
}
}
"GetUsersFromGroups" {
Write-Host "Please wait..." -NoNewLine
## If the users exists, then get the group separated by commas ##
If ($UserOrGroupNames.Count)
{
$UserOrGroupNames | % {
$SpecifiedGroup = $_ ;
Try {
$UsersInSpecifiedGroup = (Get-ADGroup -Identity $SpecifiedGroup -Properties Member -EA Stop | select-Object -Expand Member | Get-ADUser).SamAccountName
$UsersInSpecifiedGroup | Out-File -FilePath "Members of $($SpecifiedGroup).txt"
Write-Host -fore green "`r[Info]: $($UsersInSpecifiedGroup.Count) Members of `'$SpecifiedGroup`' has been saved to `'Members of $($SpecifiedGroup).txt`'"
}
catch{
Write-Host -fore red "`r[Error]: Cannot get the members of $SpecifiedGroup Group."
}
}
}
else
{
Write-Host "`r[Info]: There are not groups in the txt file or under the $OUDistinguishedName"
}
}
"GetGroupsFromUsers" {
Write-Host "Please wait..." -NoNewLine
## If the users exists, then get the group separated by commas ##
If ($UserOrGroupNames.Count)
{
$UserOrGroupNamesInfo | select SamAccountName,@{Name="MemberOf";Exp={ ((-join (($_.memberof.split(',')) -like "*cn=*") ) -replace 'CN=',",").TrimStart(",") }} | Export-Csv -NotypeInformation -Path AD_Users_and_Groups_Info.csv
## Output if file exists ##
If (Test-Path -Path AD_Users_and_Groups_Info.csv)
{
Write-Host -fore green "`r[Info]: $($UserOrGroupNames.Count) AD users and their group members list has been saved to `'AD_Users_and_Groups_Info.csv`'"
}
}
}
"AddUsersToGroup" {
If ([string]::IsNullOrWhiteSpace($GroupName))
{
Write-Host -fore red "`r[Error]: You must specify the group name with -GroupName parameter. Nothing changed. Script exits."
}
else
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users will be added to $GroupName." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
If ($UserOrGroupNames.Count)
{
$UserOrGroupNames | % {
$UserName = $_
Try {
Add-ADGroupMember -Members $_ -Identity $GroupName
Write-Host "`r[Info]: $UserName has been added to `'$GroupName`'"
$EffectiveCount++;
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
{
Write-Host -fore red "`r[Error]: `'$GroupName`' Group is not found."
}
catch [Microsoft.ActiveDirectory.Management.ADException]
{
Write-Host -fore red "`r[Error]: You do not have permisions to change membership of `'$GroupName`' Group."
}
}
Write-Host -fore green "`r$EffectiveCount users have been added to `'$GroupName`'. Script exits."
}
}
}
"RemoveUsersFromGroup" {
If ([string]::IsNullOrWhiteSpace($GroupName))
{
Write-Host -fore red "`r[Warning]: You must specify the group name with -GroupName parameter. Script exits."
}
else
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users will be removed from the `'$GroupName`'." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
If ($UserOrGroupNames.Count)
{
$UserOrGroupNames | % {
$UserName = $_
Try {
Remove-ADGroupMember -Members $_ -Identity $GroupName -Confirm:$False
Write-Host "`r[Info]: $UserName has been removed from `'$GroupName`'"
$EffectiveCount++;
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
{
Write-Host -fore red "`r[Error]: `'$GroupName`' Group is not found."
}
catch [Microsoft.ActiveDirectory.Management.ADException]
{
Write-Host -fore red "`r[Error]: You do not have permisions to change membership of `'$GroupName`' Group."
}
}
Write-Host -fore green "`r$EffectiveCount users have been removed from `'$GroupName`'. Script exits."
}
}
}
"EnableUsers" {
If ($UserOrGroupNames.Count)
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users will be enabled." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
$UserOrGroupNames | % {
$UserName = $_
Try {
Set-ADUser -Identity $UserName -Enabled:$True
Write-Host "`r[Info]: `'$UserName`' user has been enabled"
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to enable `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r$EffectiveCount users have been enabled. Script exits."
}
}
"DisableUsers" {
If ($UserOrGroupNames.Count)
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users will be disabled." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
$UserOrGroupNames | % {
$UserName = $_
Try {
Set-ADUser -Identity $UserName -Enabled:$False
Write-Host "`r[Info]: `'$UserName`' user has been disabled"
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to disable `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r$EffectiveCount users have been disabled. Script exits."
}
}
"DeleteUsers" {
If ($UserOrGroupNames.Count)
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users will be deleted." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
$UserOrGroupNames | % {
$UserName = $_
Try {
Remove-ADUser -Identity $UserName -Confirm:$False
Write-Host "`r[Info]: `'$UserName`' user has been deleted."
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to delete `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r$EffectiveCount users have been deleted."
}
}
"ResetPasswordTimeStamp" {
If ($UserOrGroupNames.Count)
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users password reset datetime stamp will be reset (extend password expiry for these users)." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
$UserOrGroupNames | % {
$UserName = $_
Try {
Set-ADUser -Identity $UserName -Replace @{pwdLastSet = 0};
Set-ADUser -Identity $UserName -Replace @{pwdLastSet = -1};
Write-Host "`r[Info]: `'$UserName`' user pwdLastSet value has been reset."
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to reset the pwdLastSet value of `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r$EffectiveCount users' pwdLastSet have been reset."
}
}
"ResetPassword" {
If ($UserOrGroupNames.Count -AND !([string]::IsNullOrWhiteSpace($PasswordString)))
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users password will be reset with `'$PasswordString`'." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
$UserOrGroupNames | % {
$UserName = $_
Try {
Set-ADAccountPassword -Identity $UserName -Reset -NewPassword (ConvertTo-SecureString -AsPlainText $PasswordString -Force);
Write-Host "`r[Info]: `'$UserName`' user password has been reset."
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to reset the password of `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r$EffectiveCount users passwords have been reset. Script exits."
}
elseIf ([string]::IsNullOrWhiteSpace($PasswordString))
{
Write-Host -fore red "`r[Error]: You need to define the password string along with the -PasswordString parameter. Eg: -PasswordString `'ASD123!@#`'"
}
else
{
## Nothing to do here
}
}
"SetAccountExpiryDate" {
## Check if the expiry date pattern is correct (MM/dd/yyyy) or empty ##
If ([string]::IsNullOrWhiteSpace($AccountExpiryDate))
{
Write-Host -fore red "`r[Error]: -AccountExpiryDate parameter must be specified. Please specify the parameter with the value in MM/dd/yyyy format or set to 'Never'. Script exits."
}
## Clear the user account expiration attribute ##
elseif ($AccountExpiryDate -match '^Never$')
{
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users account expiry date will be modified." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
$UserOrGroupNames | % {
$UserName = $_
Try {
Clear-ADAccountExpiration -Identity $UserName
Write-Host "`r[Info]: `'$UserName`' user account expiration date has been set to `'Never`'."
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to set the account expiry date of `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r[Info]: $EffectiveCount users account expiry date have been set to `'Never`'. Script exits."
}
## Set the user account expration date to specified date ##
elseif ($AccountExpiryDate -match '^((0[1-9])|(1[0-2])){1}\/((0[1-9])|(1[0-9])|(2[0-9])|(3[0-1])){1}\/\d{4}$')
{
Try {
[Datetime]$AccountExpiryDate | Out-Null; ## Check if we can covert to the actual date
## Call the function which will prompt the user about the impact ##
Prompt_User -QuestionString "[Question]: The above $($UserOrGroupNamesInfo.Count) users account expiry date will be set to $AccountExpiryDate." -UserOrGroupNamesInfo $UserOrGroupNamesInfo
Write-Host "Please wait..." -NoNewLine
## If the above parsing doesn't error, then try setting the expiry date ##
$UserOrGroupNames | % {
$UserName = $_
Try {
Set-ADAccountExpiration -Identity $UserName -DateTime $AccountExpiryDate
Write-Host "`r[Info]: `'$UserName`' user account expiration date has been set to $AccountExpiryDate."
$EffectiveCount++;
}
catch {
Write-Host -fore red "`r[Error]: You do not have permisions to set the account expiry date of `'$UserName`' user or user doesn't exist."
}
}
Write-Host -fore green "`r[Info]: $EffectiveCount users account expiry date have been set to $AccountExpiryDate. Script exits."
}
catch {
Write-Host -fore yellow "`r[Error]: The entered date $AccountExpiryDate is not realistic. Please enter the correct date. Script exits."
}
}
else
{
Write-Host -fore red "`r[Error]: -ExpiryDateor value must be in the format of MM/dd/yyyy. The entered value is $AccountExpiryDate. Script exits."
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment