Last active
November 12, 2023 12:43
-
-
Save phyoewaipaing/eb1fa6ed1111d404d3c9c0fe747ca495 to your computer and use it in GitHub Desktop.
Lock up the AD user and Add to specific Domain Security Group
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
############################################################################################################################################################################################################################################### | |
## This script will lockup the domain user in a specific computer and add this user to more privileged domain group for a short time interval ( 1 min to 24 hr ) | |
## This script must be running on the computer with RSAT tools installed or directly on a domain controller where the user running the script must be the necessary permission to change the membership of the group you want to add the user ## | |
## It will ask for the username and the computer name to lockup this user | |
## After specifying hr and min, the countdown will start | |
## It will release the user and remove from the privileged domain group when the countdown reaches zero | |
## It will do the same thing if you stop the script by pressing Ctrl+C midway | |
## The domain security group must already be added to local groups (eg: Administrators, Network Configuration Operators) of the client computers by GPO or other methods | |
## Author: Phyoe Wai Paing | |
## Country: Myanmar (Burma) | |
## v1.0 : 23.Apr.2020 : Initial Release | |
## v2.0 : 19.May.2020 : Can add multiple Logon Computers separated by commas | |
## v2.1 : 18.May.2021 : Extend the allowed duration to 3 days. Fix that multiple computers names are appended in the display output | |
################################################################################################################################################################################################################################################# | |
$GroupToAddUser = "Desktop Support Administrators" ## Change this variable to any domain security group to suite your needs unless the script is digitally signed## | |
## Resize the screen buffer size so that, we can update the timer digits later ## | |
mode 120 | |
Write-Host -fore Yellow "[Warning]: This Script will temporarily lock up the user on specific computer and escalate the privileges by adding the user to `'$($GroupToAddUser)`' domain security group.`n" | |
$OK= 0; ## Will change to 1 if the user is found ## | |
while ($InputUserName -ne 0 -AND $OK -eq 0) | |
{ | |
$InputUserName = Read-Host "Enter User Name [Press 0 to exit]"; | |
switch ($InputUserName) | |
{ | |
{ $InputUserName -match '^0$' } { Write-Host "The Script exits"; EXIT; } | |
## If the username contains @, then it must alos contain dot ## | |
{ $InputUserName -match '(^\w+\.*\w+$)(?!\w+@\w+)' } { | |
Try { | |
$UserName = (Get-ADUser -Identity $InputUserName).UserPrincipalName; | |
$UserName = $UserName.Split('@')[0] | |
Write-Host -fore green "User Name is found: $UserName"; | |
$OK=1; | |
} | |
Catch { | |
Write-Host -fore red "User Name $InputUserName is not found"; | |
} | |
} | |
## If the username contains @ (eg: user01@testdomain.local), then split and extract the username ## | |
{ $InputUserName -match '^\w+\.*\w+@\w+\.\w+$' } { $UserName = $InputUserName.Split('@')[0]; | |
Try { | |
$UserName = (Get-ADUser -Identity $UserName).UserPrincipalName; | |
$UserName = $UserName.Split('@')[0] | |
Write-Host -fore green "User Name is found: $UserName"; | |
$OK=1; | |
} | |
Catch { | |
Write-Host -fore red "User Name $InputUserName is not found"; | |
} | |
} | |
## If the username contains backslash (eg: testdomain\user01), then split and extract the username ## | |
{ $InputUserName -match '^\w+\\\w+' } { $UserName = $InputUserName.Split('\')[1]; | |
Try { | |
$UserName = (Get-ADUser -Identity $UserName).UserPrincipalName; | |
$UserName = $UserName.Split('@')[0] | |
Write-Host -fore green "User Name is found: $UserName"; | |
$OK=1; | |
} | |
Catch { | |
Write-Host -fore red "User Name Not found: $UserName"; | |
} | |
} | |
Default { Write-Host -fore red "User Name is invalid: $InputUserName"; } | |
} | |
} | |
$CompuNameArray = @(); ## Array to keep the found computer names## | |
## Prompt and Validate for the Computername ## | |
$OK=0; | |
while ($InputCompuName -ne 0 -AND $OK -eq 0) | |
{ | |
$InputCompuNames = Read-Host "Enter Computer Name [Press 0 to exit]"; | |
$InputCompuNames = $InputCompuNames -split ',' | |
foreach ($InputCompuName in $InputCompuNames) | |
{ | |
switch -Regex ($InputCompuName) | |
{ | |
'^0$' { Write-Host "The Script exits."; EXIT; } | |
## accept computer name not more than 15 characters ## | |
'^[A-Z0-9-_]{1,15}$' { | |
Try { | |
$CurCompuName = (get-adcomputer $InputCompuName -Properties Name -EA Stop ).Name; | |
$CompuNameArray += $CurCompuName; | |
Write-Host -fore green "Computer Name is found: $CurCompuName"; $OK=1; | |
} | |
catch { | |
Write-Host -fore red "Computer Name is Not found: $InputCompuName"; | |
} | |
} | |
## Check if the input value is an IP address ## | |
"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b" | |
{ | |
Try { | |
## Lookup up the PTR record to find the computername, if not ok, then query from AD ## | |
$CurCompuName = (Resolve-DnsName -Name $InputCompuName -Type PTR -DnsOnly -NoRecursion -EA Stop).NameHost.Split('.')[0] | |
$CompuNameArray += $CurCompuName | |
Write-Host -fore green "Computer Name for $InputCompuName is found: $CurCompuName"; $OK=1; | |
} | |
catch { | |
try { | |
$CurCompuName = (Get-adcomputer -Filter 'Ipv4Address -eq $InputCompuName' -EA Stop).Name | |
$CompuNameArray += $CurCompuName | |
Write-Host -fore green "Computer Name for $InputCompuName is found: $CurCompuName"; $OK=1; | |
} | |
catch { | |
Write-Host -fore red "Computer Name for $InputCompuName is Not found"; | |
} | |
} | |
} | |
Default | |
{ Write-Host -fore red "Computer Name `'$InputCompuName`' is invalid." } | |
} | |
} | |
} | |
## Create the $Duration hash table so that we can pass it to switch statement ## | |
$Duration = @{} | |
$OK = 0; | |
## Prompt user for hour and minutes information. It will constantly prompt if more than 24hr is entered ## | |
while ($OK -eq 0) | |
{ | |
$Duration["Hr"] = Read-Host "`nHow many hours do you want to lock up this user?[Press x to exit, 0 for less than 1 hr]" | |
If ($Duration["Hr"] -eq 'x') { Write-Host "[X] is detected. The Script exits."; EXIT; } | |
$Duration["Min"] = Read-Host "How many minutes do you want to lock up this user?[Press x to exit]" | |
switch($Duration) | |
{ | |
{$Duration["Hr"] -match "^[x]$" -OR $Duration["Min"] -match "^[x]$" } { Write-Host "[X] is detected. The Script exits."; EXIT; } | |
{$Duration["Hr"] -le 72 -AND $Duration["Min"] -eq 0 } { $DurationSeconds = ($Duration["Hr"] * 3600) + ($Duration["Min"] * 60); $OK = 1; } | |
{$Duration["Hr"] -le 71 -AND $Duration["Min"] -lt 60 } { $DurationSeconds = ($Duration["Hr"] * 3600) + ($Duration["Min"] * 60); $OK = 1; } | |
Default { Write-Host -fore yellow "You can only specify the time less than 72hr"; } | |
} | |
} | |
## Create the $DurationSeconds variable to compare in the next while loop section ## | |
$DurationSeconds = ([int]$Duration["Hr"] * 3600) + ([int]$Duration["Min"] * 60) | |
### If the user running the script does not have the necessary permission to modify the target user, then output the error message ### | |
Try { | |
$CompuNameArrayString = $CompuNameArray -join ','; | |
## Lock down the user to specific computer ## | |
Set-ADUser -Identity $UserName -LogonWorkstations $CompuNameArrayString -Confirm:$false | |
## Add the user to the specific security group (for privilege escalation) ## | |
Add-ADGroupMember -Identity $GroupToAddUser -Members $UserName -Confirm:$false | |
## Output the information with colorized computer name ## | |
Write-Host "`nThis windows will automatically close after user is unlocked from " -NoNewline | |
## Write back the computer name to the end of the previous line ## | |
## Move x coordinate by 66 chracters to write the Computer Name in Color ## | |
Write-Host -fore green $CompuNameArrayString; | |
Write-Host "If you want to unlock immediately, press Ctrl+C" | |
Write-Host "Remaining Time to unlock `'$UserName`' from computer: " -NoNewline | |
$origpos = $host.UI.RawUI.CursorPosition; ## Keep the current position so that the hr,min,sec digits can write back to the blank spaces in the next while loop section## | |
$JumpSpaces= " Hours Minutes Seconds" | |
Write-Host $JumpSpaces -NoNewline | |
$Counter=0 | |
## Loop the 1 sec counter and match with the converted total seconds value ## | |
while ($Counter -le $DurationSeconds ) | |
{ | |
$TimeSpan = [timespan]::fromseconds($DurationSeconds - $Counter) | |
$CurHours = $TimeSpan.TotalHours | |
$CurMinutes = $TimeSpan.Minutes | |
$CurSeconds = $TimeSpan.Seconds | |
## Get the start coordindates of the line where the rotating time digits are displayed ## | |
$newgpos = $origpos | |
$newgpos.X = $origpos.X + $JumpSpaces.Length - 30 ## Move 30 characters to the left from the end of the line. | |
$host.UI.RawUI.CursorPosition = $newgpos | |
$CurHoursText = "{0:00}" -f $CurHours | |
Write-Host -fore yellow $CurHoursText -NoNewline | |
## Get the start coordindates of the line where the rotating time digits are displayed ## | |
$newgpos = $origpos | |
$newgpos.X = $origpos.X + $JumpSpaces.Length - 21 ## Move 21 characters to the left from the end of the line. | |
$host.UI.RawUI.CursorPosition = $newgpos | |
$CurMinutesText = "{0:00}" -f $CurMinutes | |
Write-Host -fore yellow $CurMinutesText -NoNewline | |
## Get the start coordindates of the line where the rotating time digits are displayed ## | |
$newgpos = $origpos | |
$newgpos.X = $origpos.X + $JumpSpaces.Length - 10 ## ## Move 10 characters to the left from the end of the line. | |
$host.UI.RawUI.CursorPosition = $newgpos | |
$CurSecondsText = "{0:00}" -f $CurSeconds | |
Write-Host -fore yellow $CurSecondsText | |
$Counter++ | |
Start-Sleep 1; | |
## Capture the Ctrl+C Break ## | |
[Console]::TreatControlCAsInput = $True | |
while ($Host.UI.RawUI.KeyAvailable -and ($Key = $Host.UI.RawUI.ReadKey("AllowCtrlC,NoEcho,IncludeKeyUp"))) | |
{ | |
If ([Int]$Key.Character -eq 3) { | |
## Remove User from the specific group membership ## | |
Remove-ADGroupMember -Identity $GroupToAddUser -Members $UserName -Confirm:$false; | |
## Release the user from specific computere ## | |
Set-ADUser -Identity $UserName -LogonWorkstations $NULL -Confirm:$false; | |
Write-Host -fore DarkYellow "Ctrl+C pressed. `'$UserName`' is removed from `'$GroupToAddUser`' and unlocked from `'$($CompuNameArray -join ',')`' immediately." | |
exit; | |
} | |
$Host.UI.RawUI.FlushInputBuffer() | |
} | |
} | |
#### Actions to do when the timer reaches zero ### | |
## Remove User from the specific group membership ## | |
Remove-ADGroupMember -Identity $GroupToAddUser -Members $UserName -Confirm:$false; | |
## Release the user from specific computere ## | |
Set-ADUser -Identity $UserName -LogonWorkstations $NULL -Confirm:$false; | |
} | |
catch [Microsoft.ActiveDirectory.Management.ADException] | |
{ | |
Write-Host -fore red "You do not have necessary permission to lockup the user and add into `'$($GroupToAddUser)`' group. Script Exits." | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment