Prompt for Credentials Repeatedly in Powershell - powershell

I have the below code which prompts for username and password, and if incorrect has the right exceptions that are caught in the catch statement. However, how do I ensure I repeatedly prompt for username and password until a correct one is entered?
Another question is how do I convert the password entered into a secure string. Any help is greatly appreciated.
$TS_Deploy_Group = "MYADGROUP"
$get_AD_Server = (Get-WmiObject -Class Win32_NetWorkAdapterConfiguration | Where-Object { $_.DNSDomain -like "***-**.contoso.com"}).DnsDomain
if ($get_AD_Server -ne $null)
{
$get_Nearest_DC = (Get-ADDomainController -DomainName $get_AD_Server -Discover -NextClosestSite).Name
$AD_Server = $get_Nearest_DC,$get_AD_Server -join "."
$cred = $host.ui.PromptForCredential("Authenticate to OSD:", "Enter your Operator Credentials", "", "")
}
else
{
[System.Windows.Forms.MessageBox]::Show("Please make sure you are connected to the Corporate Network")
}
Try
{
$ADauth = Get-ADGroupMember -Identity $TS_Deploy_Group -Recursive -Server $AD_Server -Credential $cred
}
Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
{
[System.Windows.Forms.MessageBox]::Show("The user" +$cred.username+ "has not been found", "User not found")
}
Catch [Microsoft.ActiveDirectory.Management.ADServerDownException]
{
[System.Windows.Forms.MessageBox]::Show("Check the server name or IP configuration", "Error while contacting AD Server")
}
Catch [System.Security.Authentication.AuthenticationException]
{
[System.Windows.Forms.MessageBox]::Show("Please check the admin user name or password", "Invalid credentials")
}
if (($ADauth.name -Contains $cred.username) -ne $true) {
[System.Windows.Forms.MessageBox]::Show("The specified user is not member of the group:
$TS_Deploy_Group", "Unauthorized user")
exit
}
Finally
{
[System.Windows.Forms.MessageBox]::Show("Task Sequence Will Continue to the Next Step")
}

I would do something like this:
while($true)
{
Try
{
$ADauth = Get-ADGroupMember -Identity $TS_Deploy_Group -Recursive -Server $AD_Server -Credential $cred
break
}
Catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException]
{
[System.Windows.Forms.MessageBox]::Show("The user" +$cred.username+ "has not been found", "User not found")
$cred = $host.ui.PromptForCredential("Authenticate to OSD:", "Enter your Operator Credentials", "", "")
}
Catch [Microsoft.ActiveDirectory.Management.ADServerDownException]
{
[System.Windows.Forms.MessageBox]::Show("Check the server name or IP configuration", "Error while contacting AD Server")
}
Catch [System.Security.Authentication.AuthenticationException]
{
[System.Windows.Forms.MessageBox]::Show("Please check the admin user name or password", "Invalid credentials")
$cred = $host.ui.PromptForCredential("Authenticate to OSD:", "Enter your Operator Credentials", "", "")
}
}

Related

How do I use a switch statement with while loop

I am trying to add a user to the Remote Desktop group using Powershell.
It seems it's not breaking the loop and doesn't execute further statements.
Can you please help me where the issue is:
$remote = ""
While($remote -ne "Y" ){
$remote = read-host "Do you need to add anyone to the Remote Desktop group (y/n)?"
Switch ($remote)
{
Y {
$remoteuser = ""
while ( ($remoteuser -eq "") -or ($UserExists -eq $false) )
{
$remoteuser = Read-Host "Enter the username that needs to be in the group"
Write-Host "User inputted $remoteuser"
sleep -Seconds 2
try {
Get-ADUser -Identity $remoteuser -Server <server-FQDN>
$UserExists = $true
Write-Host "$remoteuser found!"
sleep 5
}
catch [Microsoft.ActiveDirectory.Management.ADIdentityResolutionException] {
Write-Host "User does not exist."
$UserExists = $false
}
catch {
Write-Host "Username is blank"
$UserExists = $false
}
}
}
N {Write-Host "No user accounts will be added to the Remote Desktop Users group. Restart your PC."}
default {Write-Host "Only Y/N are Valid responses"}
}
}
<further statements>

How can I turn this exceptional error message into my custom message in PowerShell?

I am writing the script which should validate the user in the active directory and gets some AD information. I am struggling with the error handling in this script:
$user = (Read-Host -Prompt 'Enter your network id').ToUpper()
#check if the user exists in the AD database
$userid= Get-ADUser $user | Select SamAccountName
$userid = $user
if (($user -match $userid)) {
Write-Host $user "exists in AD"
}else{
write-host "user cannot be found"
}
If someone who uses the script will put incorrect userId (which doesn't exist in AD), the script will throw an error message :
Get-ADUser : Cannot find an object with identity: 'DUMMY' under: 'DC=company,DC=com'.
At line:9 char:11
+ $memoid = Get-ADUser $user | Select SamAccountName
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (DUMMY:ADUser) [Get-ADUser], ADIdentityNotF
oundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.
ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Even though incorrect userID was entered, I receive
= DUMMY exists in AD
How can I turn this exceptional error message into my custom message - "The user doesn't exist in AD"? Thank you in advance
For this, it is better not to use the -Identity parameter (which you imply in your code by using Get-ADUser $user)
Try
$userID = Read-Host -Prompt 'Enter your network id'
# check if the user exists in the AD database
# this will either return an ADUser object or $null
$user = Get-ADUser -Filter "SamAccountName -eq '$userID'" -ErrorAction SilentlyContinue
if ($user) {
Write-Host "$($user.SamAccountName) exists in AD" -ForegroundColor Green
}
else{
Write-Host "user $($user.SamAccountName) cannot be found" -ForegroundColor Red
}
You need to catch the exceptions using try/catch
In the error message, it is telling that "cannot find that object"
So, your first approach is to check whether the user exists or not in the If statement and then put them in try/catch like below
try{
$user = (Read-Host -Prompt 'Enter your network id').ToUpper()
#check if the user exists in the AD database
$userid= Get-ADUser $user | Select SamAccountName
$userid = $user
if (($user -match $userid)) {
Write-Host $user "exists in AD"
}else{
write-host "user cannot be found"
}
}
catch
{
#Your Custom Message in case of the error is coming in Std Out . $_.Exception.Message will catch the exact error message.
"Error Message: "+ "$_.Exception.Message"
}
The statement: $userid = $user needs to be deleted. As is it insures that you always have a match.
Next place your call to Get-ADUser in a Try/Catch construct to catch the error.
$user = (Read-Host -Prompt 'Enter your network id').ToUpper()
#check if the user exists in the AD database
Try {
$userid= Get-ADUser $user -EA "STOP" | Select SamAccountName
Write-Host $user "exists in AD"
}
Catch {
#*** Process errors here ***
write-host "user cannot be found"
Exit
}
#Continue your script here
Note: I don't have access to a Server so this is untested but should work in theory!
HTH

If error, skip to next in Powershell (Microsoft Teams)

Good evening,
I have written a piece of code in Powershell that takes a .csv file as input, and create a new
Microsoft Team with the channels and users in the .csv
The script is working, but i dont really like the part where i add the owners to the team. I recieve a list of ID's in the .csv file, but i can only add the owners with a mailadres. This would be a easy loop, but there are 3 possible domains that the user is connected to.
My goal is to have a piece of code that adds #domain1.nl to the ID that i get in the .csv, and try to add the user. if i receive a error because that address does not exist, it will try to add the owner with #domain2.nl and #domain3.nl added to it. If nothing works, it should give a Write-Host that says "This domain has to be added"
Below is the piece of code that works, but i think its not the best way to it and it could be improved.
#Adding the owners to the Team
if ($d.ID) {
$Error.Clear()
try {
$ID = $d.ID + "#domain1.nl"
Add-TeamUser -GroupId $GroupID -User $ID -Role Owner
} catch { "Error occured" }
if ($Error) {
$Error.Clear()
try {
$ID = $d.ID + "#domain2.nl"
Add-TeamUser -GroupId $GroupID -User $ID -Role Owner
} catch { "Error occured" }
if ($Error) {
$Error.Clear()
try {
$ID = $d.ID + "#domain3.nl"
Add-TeamUser -GroupId $GroupID -User $ID -Role Owner
} catch { "Error occured" }
if ($Error) {
Write-Host "This domain has to be added to the code"
}
}
}
}
Many thanks in advance!
Use try / catch inside a foreach loop:
$ok = $false
foreach ($domain in '#domain1.nl', '#domain2.nl', '#domain3.nl') {
try {
Add-TeamUser -GroupId $GroupID -User ($d.ID + $domain) -Role Owner
$ok = $true
} catch {
Write-Warning "Error occurred with domain $domain."
}
if ($ok) { break }
}
if (-not $ok) {
Write-Error 'This domain has to be added to the code'
}

Powershell: How to request user authentication to continue

My Powershell script has some features/functions implemented, but there are some features that I want to restrict to some users.
In order to allow the current user or a different user to select such restricted features from the menu, I am looking for a way to require user authentication from Windows to continue. How could I do that? How the UserAuthentication function below should be like?
Code:
$feature = Read-Host 'Select the feature by typing the number [1 - 2]'
switch ($feature)
{
1
{
write-output "This feature any user can reach"
}
2
{
$user = Read-Host "This feature only some user can reach and requires authentication. Entry your username to proceed"
$allowedUsers = "user1", "user2"
if($allowedUsers.contains($user))
{
write-output "This feature the user $user can reach. Please authenticate to continue"
if((UserAuthentication $user) -eq $true)
{
write-output "$user successfully authenticated"
}
else
{
write-output "$user unsuccessful authenticated"
}
}
else
{
write-output "This feature the user $user cannot reach"
}
}
}
function UserAuthentication($user)
{
return $true #May return 'True' if successfully authenticated or 'False' if not.
}
This answer is for when your users are member of an AD domain
I have changed the function name UserAuthentication to Get-Authentication to comply with the Verb-Noun function naming convention in PowerShell.
# helper function test if a username/password combination is valid.
# if valid, the username entered in the box is returned.
function Get-Authentication {
$Credentials = Get-Credential "$env:USERDOMAIN\$env:USERNAME" -Message "Please authenticate to continue" -ErrorAction SilentlyContinue
if ($Credentials) {
$UserName = $Credentials.UserName
$Password = $Credentials.GetNetworkCredential().Password # --> plain-text password
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ds = New-Object System.DirectoryServices.AccountManagement.PrincipalContext Domain
if ($ds.ValidateCredentials($UserName, $Password)) {
# return the username entered
$UserName
}
}
}
# your code here
# fill in the SamAccountNames of allowed users for this feature
$allowedUsers = 'samaccountname','of', 'users', 'that', 'are', 'allowed', 'to', 'use', 'feature 2'
$feature = Read-Host 'Select the feature by typing the number [1 - 2]'
switch ($feature) {
'1' { Write-Output "This feature any user can reach" }
'2' {
$user = Get-Authentication
if ($null -ne $user -and $allowedUsers -contains $user) {
Write-Output "User $user is allowed for this feature"
}
else {
Write-Output "This feature the user cannot reach"
}
}
}

Powershell-else in try/catch

I'm trying to write output when get-addomain succeded.
Try/catch writes output only if command fails
try {
get-addomain -Identity d.contoso.com
}
catch {
Write-Output "failed"
}
I tried following:
if (-not (get-addomain -Identity d.contoso.com))
{
return "failed"
}
else
{
write-output "ok"
}
and
If (get-addomain -Identity d.contoso.com )
{
Write-Output "ok"
}
Else
{
write-output "failed"
}
but in both cases got
get-addomain : Cannot find an object with identity: 'd.contoso.com' under: 'DC=ad,DC=contoso,DC=com'.
The tryblock runs until a error is getting thrown. If get-addomain doesn't end with an error, the try-case will run the following commands written inside the {}.
So one way would be to just say the output is ok if no error gets thrown:
try {
get-addomain -Identity d.contoso.com
Write-Output "ok"
}
catch {
Write-Output "failed"
}
But if you want to double check, you can still do the if check in the try-catch:
try {
If (get-addomain -Identity d.contoso.com )
{
Write-Output "ok"
}
Else
{
write-output "failed"
}
}
catch {
Write-Output "failed"
}
try{
$domain = Get-ADDomain -Identity d.contoso.com
Write-Output $domain
}catch{
Write-Output "Failed with message '$($_.Exception.Message)'"
}
When you use the AD CmdLets, it fails when a non-existing identity is specified. Therefore if the object you search for does not exist, you will end up in the catch. The first piece of code you wrote is actually correct if you wish to output the AD domain information.