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"
}
}
Ok, try like this
$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
Basically, you could do something like this
$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
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.
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.
$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
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"
}
}
}
Ok, try like this
$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
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.
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
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
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 !
Try replacing the
Get-VMHost -PipelineVariable esx
with
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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,
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
The logic is in the Where-clause.
There are 2 possible cases:
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
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
<#
.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
}
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
That should work.
Replace the line
Blog: lucd.info Twitter: @LucD22 Co-author PowerCLI Reference
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
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