Change the root password in hosts and Host Profiles
For good security measures you should change the password of your root account on your ESX(i) servers on a regular basis. Instead of logging on to each and everyone of your ESX(I) servers, you can easily automate this process.
But what about the new ESX(i) hosts you will roll out in between root password changes and where you use a Host Profile to configure these new ESX(i) hosts ? Will you need to run a script after the deployment to change the root password ?
Turns out that you can easily update the root password in your Host Profile with the help of an SDK method.
The installed hosts
There are numerous scripts available in the blogosphere to accomplish this. But for good measure, this is one script that can do the task.
$currentPswd = "currentPassword"
$newPswd = "newPassword"
$excludeServers = "esx51","esx56"
$multiState = (Get-PowerCLIConfiguration).DefaultVIServerMode
$warnings = (Get-PowerCLIConfiguration).DisplayDeprecationWarnings
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Confirm:$false -DisplayDeprecationWarnings:$false | Out-Null
Get-VMHost | where{$excludeServers -notcontains $_.Name.Split('.')[0]} | %{
Connect-VIServer -Server $_.Name -User root -Password $currentPswd | Out-Null
Write-Verbose "Connected to $_"
Set-VMHostAccount -UserAccount root -Password $newPswd -Confirm:$false | Out-Null
Disconnect-VIServer -Server $_.Name -Confirm:$false
}
Set-PowerCLIConfiguration -DefaultVIServerMode $multiState -DisplayDeprecationWarnings $warnings -Confirm:$false | Out-Null
Annotations
Line 1-2: Provide the current and the new password for the root account.
Line 4: The script allows for ESX(i) hosts whose root password should not be changed to the password specified in this run of the script. These ESX(i) hosts can excluded by adding their hostname to this array.
Line 6-8: The script needs to run in Multiple mode, in other words it needs connections to multiple vSphere servers at the same time. For the run of this script I also disable the warning messages for deprecated properties, this to avoid a long list of warning messages. The script remembers the current settings before changing them.
Line 10: The script gets all the ESX(i) servers and excludes the ones we defined in the array in line 4.
Line 11-14: The script makes a connection to the ESX(i) server and changes the password of the root account.
Line 12: If you want to track the ESX(i) hosts for which the script is changing the root password, you can set the $verbosePreference variable to Continue instead of the default SilentlyContinue.
Line 17: The script restores the PowerCLI Configuration settings.
The Host Profile
When you use Host Profiles to configure your newly deployed ESX(i) servers, you will need to update the root account in those Host Profiles on a regular basis as well. That way the new ESX(i) hosts you roll out will immediately have the current root password.
function Set-VMHostProfileExtended{
<#
.SYNOPSIS Update the root password in a Host Profile
.DESCRIPTION The function will update the root password in
a Host Profile.
.NOTES Author: Luc Dekens
.PARAMETER Profile
The Host Profile for which you want to change the root
password. You can pass the name of the Host Profile
or the VMHostProfile object
.PARAMETER AdminPassword
The new root password.
.EXAMPLE
PS> $prof = Get-VMHostProfile -Name MyProfile
PS> Set-VMHostProfileExtended -Profile $prof -AdminPassword "abc"
#>
param(
[CmdletBinding()]
[parameter(Mandatory = $true, ValueFromPipeline = $true)]
[PSObject]$Profile,
[string]$AdminPassword
)
begin{
function Copy-Property ($From, $To, $PropertyName ="*")
{
foreach ($p in Get-Member -In $From -MemberType Property -Name $propertyName)
{ trap {
Add-Member -In $To -MemberType NoteProperty -Name $p.Name -Value $From.$($p.Name) -Force
continue
}
$To.$($P.Name) = $From.$($P.Name)
}
}
}
process{
if($Profile.GetType().Name -eq "string"){
$Profile = Get-VMHostProfile -Name $Profile -Server $defaultVIServers[0]
}
$spec = New-Object VMware.Vim.HostProfileCompleteConfigSpec
Copy-Property -From $Profile.ExtensionData.Config -To $spec
$secpol = New-Object VMware.Vim.ProfilePolicy
$secpol.Id = "AdminPasswordPolicy"
$secpol.PolicyOption = New-Object VMware.Vim.PolicyOption
$secpol.PolicyOption.Id = "FixedAdminPasswordOption"
$secpol.PolicyOption.Parameter += New-Object VMware.Vim.KeyAnyValue
$secpol.PolicyOption.Parameter[0].Key = "password"
$secpol.PolicyOption.Parameter[0].Value = New-Object VMware.Vim.PasswordField
$secpol.PolicyOption.Parameter[0].Value.Value = $AdminPassword
$spec.ApplyProfile.Security.Policy = @($secpol)
$Profile.ExtensionData.UpdateHostProfile($spec)
Get-VMHostProfile -Name $Profile.Name
}
}
Annotations
Line 26-35: The function needs to copy all the Config properties from the HostProfile to the HostProfileCompleteConfigSpec object. Instead of reinventing the wheel, I used a function called Copy-Property function from Dennis Verwiej.
Line 39-41: My simplistic Object By Name (OBN) implementation.
Line 45: The copy of the Config property to the HostProfileCompleteConfigSpec object.
Line 47-55: To the copied HostProfile configuration the script adds the AdminPasswordPolicy definitions.
Line 57: The HostProfile is updated with the UpdateHostProfile method.
Line 59: To emulate the behaviour of the Set-VMHostProfile cmdlet, the function places the updated VMHostProfile object on the pipeline.
Sample usage
The function to update the Host Profile can be called with the Host Profile as a parameter.
$hostProf = "MyProfile" $newProf = Set-VMHostProfileExtended -Profile $hostProf -AdminPassword "secret"
or
$hostProf = Get-VMHostProfile -Name MyProfile $newProf = Set-VMHostProfileExtended -Profile $hostProf -AdminPassword "secret"
Or you can place the Host Profile on the pipeline.
Get-VMHostProfile -Name MyProfile | Set-VMHostProfileExtended -AdminPassword "secret"
Notice that I called the function Set-VMHostProfileExtended. The reason for that is that one can update several other settings in a Host Profile this way. I’ll probably add some other settings to the function in a later stage.
Enjoy !

I’m assuming that the first script requires a connect-viserver line at the beginning. Or do I need to modify line 11? I’m new to powershell.
@Natasha, the first script needs indeed a Connect-ViServer to the vCenter when you run it.
The script will then connect to each ESX(i) host (line 11) to update the password. For that you will need to update the variable in line 1. Line 2 is of course the new password.
There is a mismatch between the line numbering of the second script and the annotations. E.g. Line 0-19 should be Line 26-35.
You probably added the comment at the beginning of the function after writing the annotations section.
Thanks for catching that one Robert.
I corrected the line numbering