VMware Cloud Community
virtualtech_wor
Enthusiast
Enthusiast
Jump to solution

Validate ESXi root password against multiple passwords

We have esxi hosts with different root passwords spread across. Need to validate at least 3 passwords on each of the host and log the status as we validate.

Trying something like this but the code could validate only 2 passwords. Also, looking for a better code to validate n (2,3,4 so on.) number of passwords possibly per host.

Appreciate your inputs.

(I understand this is not the secure way to pass the password to variables, i will handle it later though)

Import-Module VMware.VimAutomation.Core

$username = root

$password1 = PASS1

$password2 = PASS2

$password3 = PASS3

$hstlist = Get-Clipboard

$Logfile = "E:\Scripts\Authentication-Check\ScriptLog-Host-$Date.log"

    Function LogWrite

                {

                    Param ([string]$logstring)

                    Add-content $Logfile -value $logstring

                }

foreach ($vmhost in $hstlist){

$global:DefaultVIServer = $null

$global:DefaultVIServers = $null

$Conn = Connect-VIServer -Server $vmhost -User $username -Password $password1

if ($Conn) {

LogWrite "Authenticated host $vmhost using password 1"

}

else{

    Connect-VIServer $vmhost -User $username -Password $password2

    LogWrite "Authenticated host $vmhost using password 2"

}

}

1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

Ok, try like this

$esxNames = 'esx1', 'esx2', 'esx3'

$user = 'root'

$pswds = 'pswd1', 'pswd2', 'pswd3'


foreach ($esx in $esxNames)

{

   $i = 1

   foreach ($pswd in $pswds)

   {

   try

   {

   Connect-VIServer -Server $esx -User $user -Password $pswd -ErrorAction Stop | Out-Null

  LogWrite "Host $esx password$i is correct"

   Disconnect-VIServer -Server $esx -Confirm:$false

   break

   }

   catch

   {

  LogWrite "Host $esx password$i failed"

   }

   $i++

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

Reply
0 Kudos
16 Replies
LucD
Leadership
Leadership
Jump to solution

Basically, you could do something like this

$user = 'root'

$pswds = 'pswd1', 'pswd2', 'pswd3'


Get-VMHost -PipelineVariable esx |

ForEach-Object -Process {

   foreach ($pswd in $pswds)

   {

     try

     {

       Connect-VIServer -Server $esx.Name -User $user -Password $pswd -ErrorAction Stop | Out-Null

       Write-Host "Host $($esx.Name) password $pswd is correct"

       Disconnect-VIServer -Server $esx.Name -Confirm:$false

     }

     catch

     {

       Write-Host "Host $($esx.Name) password $pswd failed"

     }

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
virtualtech_wor
Enthusiast
Enthusiast
Jump to solution

Thanks, that helps for handling multiple passwords.

However, if I have custom list of Hosts (from different vCenters) instead of using Get-VMHost do I need to use foreach to loop through esxi hosts on top of the foreach for passwords?

Please advise.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

You don't have to change a lot for that.

You could do something like this.
This can easily be adapted if the hostnames come in a file.

$esxNames = 'esx1','esx2'

$user = 'root'

$pswds = 'pswd1', 'pswd2', 'pswd3'


Get-VMHost -Name $esxNames -PipelineVariable esx |

ForEach-Object -Process {

   foreach ($pswd in $pswds)

   {

   try

   {

   Connect-VIServer -Server $esx.Name -User $user -Password $pswd -ErrorAction Stop | Out-Null

   Write-Host "Host $($esx.Name) password $pswd is correct"

   Disconnect-VIServer -Server $esx.Name -Confirm:$false

   }

   catch

   {

   Write-Host "Host $($esx.Name) password $pswd failed"

   }

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
virtualtech_wor
Enthusiast
Enthusiast
Jump to solution

I understand Get-VMHost cmdlet can be used only if we are connected to some vCenter.

In my case, I just have random list of esxi hosts from different vCenters. Changed the code as below, it did execute.

1. Can we stop the try, if specific password works for specific host instead of it trying to validate all passwords against the host.

2. As I'm trying to log the output, it's copying the password values as is, looking for a way to use some sort of alias for the password value like first password need to be logged as password1 instead of the real password and so on.

foreach ($esx in $esxNames) {

   foreach ($pswd in $pswds)

   {

   try

        {

       #Connect-VIServer -Server $esx.Name -User $user -Password $pswd -ErrorAction Stop | Out-Null

       Connect-VIServer -Server $esx -User $user -Password $pswd -ErrorAction Stop | Out-Null

       LogWrite "Host $esx password $pswd is correct"

       Disconnect-VIServer -Server $esx -Confirm:$false

        }

   catch

       {

       LogWrite "Host $esx password $pswd failed"

       }

   }

}

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Ok, try like this

$esxNames = 'esx1', 'esx2', 'esx3'

$user = 'root'

$pswds = 'pswd1', 'pswd2', 'pswd3'


foreach ($esx in $esxNames)

{

   $i = 1

   foreach ($pswd in $pswds)

   {

   try

   {

   Connect-VIServer -Server $esx -User $user -Password $pswd -ErrorAction Stop | Out-Null

  LogWrite "Host $esx password$i is correct"

   Disconnect-VIServer -Server $esx -Confirm:$false

   break

   }

   catch

   {

  LogWrite "Host $esx password$i failed"

   }

   $i++

   }

}


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
virtualtech_wor
Enthusiast
Enthusiast
Jump to solution

Thank you. That works.

Before I mark this question as answered, how do I properly copy paste the code like you during the responses, with those actual coding style/colors.

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

When you use the Visual Studio Code editor, you can just copy the code from there.
It will be copied as HTML


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

piercj2
Enthusiast
Enthusiast
Jump to solution

HI Guys,

sorry to be revisiting a thread that's been marked as correct already but, this looks like a really handy bit of code and i was trying (without success) to modify it so that

  1. you can give two parameters (username + password) and it will check all Hosts in a VC - you have this working already
  2. you can give 3 parameters (username, Password + Hostname) and it will check only that host (or list of hosts)

I haven't been able to figure out how to change the "Get-VMHost -PipelineVariable esx | ForEach-Object" line so that it checks for the $ESXiHost variable. If the variable has been passed, only check those hosts, if it has not been passed, check all Hosts.

I've written a second function what works for the 3 variable option but, having two functions to do basically the same thing seems redundant and i suspect PowerCLI should be able to do this in one ?

function Check-Credentials {

    <#

    .SYNOPSIS

    Checks ESXi Host Credentials

    .DESCRIPTION

    Accepts Username,Password & Hostname parameters, attempts to login to the Host using provided credentials,

    If only Username and Password are passed, attempts to login to all ESXi Hosts in the VC. Creates logfile with results

    .EXAMPLE

    Check-Credentials root password 'MyEsxiHost.mycorp.com'

     .EXAMPLE

     Check-Credentials root password

    #>

    [CmdletBinding()]

    param (

        [Parameter(Mandatory=$true, Position=0)]

        [string] $user,

        [Parameter(Mandatory=$true, Position=1)]

        [string[]] $passwds,

        [Parameter(Mandatory=$false, Position=2)]

        [string[]] $ESXiHost

    )

    $Logfile = "C:\Temp\CredentialLog-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".log"

    Function LogWrite {

        Param (

            [string]$logstring

        )

        Add-content $Logfile -value $logstring

    }

    Get-VMHost -PipelineVariable esx | ForEach-Object -Process {

        foreach ($passwd in $passwds){

            try {

                Connect-VIServer -Server $esx.Name -User $user -Password $passwd -ErrorAction Stop | Out-Null

                LogWrite "Host $($esx.Name) password $passwd is correct"

                Disconnect-VIServer -Server $esx.Name -Confirm:$false

            }

            catch {

                LogWrite "Host $($esx.Name) password $passwd failed"

            }

        }

    }

Invoke-Item $Logfile

}

Thanks in advance !

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try replacing the

Get-VMHost -PipelineVariable esx

with

Get-VMHost -PipelineVariable esx | where { ($ESXiHost -and $ESXiHost -contains $_.Name) -or -not $ESXiHost }


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
piercj2
Enthusiast
Enthusiast
Jump to solution

Thanks Luc,

I don't understand the syntax you've given but, on the commute home today i think i may have thought of a different approach.

I'm going to try checking if the $ESXiHost variable is empty,

  • if empty, proceed with "Get-VMHost -PipelineVariable esx"
  • if not empty, try using "foreach ($h in $ESXiHost){...}

To check for an empty/null variable i think "if (!$ESXiHOST)..." should work.

I'll try it when i get to the office in the morning

Thanks again

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The logic is in the Where-clause.
There are 2 possible cases:

  1. $ESXiHost is empty (-not $ESXiHost will then return $true)
  2. $ESXIHost is not empty
    1. Then make sure you only allow the ESXi nodes through that have a name that is specified in $ESXiHosts

These 2 possibilities are combined with an "OR", if either of the 2 is $true, the ESXi node passes through the Where-clause


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

piercj2
Enthusiast
Enthusiast
Jump to solution

That worked perfectly Luc, thanks.

below is the working code for anyone who wants it. thanks also to the original poster for starting this off

function Check-Credentials {

   <#

   .SYNOPSIS

  Checks ESXi Host Credentials

   .DESCRIPTION

  Accepts Username,Password & Hostname parameters, attempts to login to the Host using provided credentials,

  If only Username and Password are passed, attempts to login to all ESXi Hosts in the VC. Creates logfile with results

   .EXAMPLE

  Check-Credentials root password

   .EXAMPLE

  Check-Credentials root password1,password2

   .EXAMPLE

  Check-Credentials root password MyESXiHost.mycorp.com

   .EXAMPLE

  Check-Credentials root password3,password4 MyESXiHost.mycorp.com

  #>


  [CmdletBinding()]

   param (

  [Parameter(Mandatory=$true, Position=0)]

  [string] $user,

  [Parameter(Mandatory=$true, Position=1)]

  [string[]] $passwds,

  [Parameter(Mandatory=$false, Position=2)]

  [string[]] $ESXiHost

  )


   $Logfile = "C:\Temp\CredentialLog-" + (Get-Date -Format yyyy-MMM-dd-HHmm) + ".log"

   Function LogWrite {

   Param (

  [string]$logstring

  )


   Add-content $Logfile -value $logstring

  }

   Get-VMHost -PipelineVariable esx | where { ($ESXiHost -and $ESXiHost -contains $_.Name) -or -not $ESXiHost } | ForEach-Object -Process {

   foreach ($passwd in $passwds){

   try {

   Connect-VIServer -Server $esx.Name -User $user -Password $passwd -ErrorAction Stop | Out-Null

  LogWrite "Host $($esx.Name) password $passwd is correct"

   Disconnect-VIServer -Server $esx.Name -Confirm:$false

  }

   catch {

  LogWrite "Host $($esx.Name) password $passwd failed"

  }

  }

  }

Invoke-Item $Logfile

}

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

Hi LucD,

Sorry for revisiting the thread again. Can we validate around 500 ESXi host root password running across multiple vCenter ? Example - C:\temp\list.txt or inventory.csv

Note :- ESXi host might have 2 to 3 different password as you mentioned in your script - $pswds = 'pswd1', 'pswd2', 'pswd3'

Thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

That should work.

Replace the line

$esxNames = 'esx1', 'esx2', 'esx3'

with for example
$esxNames = Get-Content -Path 'C:\temp\list.txt'


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
vmk2014
Expert
Expert
Jump to solution

Thank you, LucD.

Do we need to enable SSH service prior to running the script ? If yes, then can we enable SSH service prior to running ?

Thanks

V

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

No SSH required, the script uses the Connect-VIServer cmdlet to check the validity of the password.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference