Save to My DOJO
Security is now becoming more and more demanding than ever in IT. Not only are we forced to play the cat and mouse game with never-ending security vulnerability patches, but we are also forced to keep our infrastructure within certain guidelines for compliance. Whether it’s to pass a financial or health audit, there are always security restrictions that must be put in place in order to successfully pass these inspections. If you’ve ever been tasked with implementing password rotations on a timely basis then I’m sure you can understand the headaches with coming up with a solution for each system. Luckily, we can use PowerCLI to perform our password changes on ESXi within minutes. In this post, I’ll show you how.
Changing Root on Multiple Hosts from the Console
First, we’ll go over how to change the root passwords of all the hosts immediately from the PowerShell console. This is super useful if an IT employee or someone who had access to all passwords leaves the company or is terminated. In these instances, a password change throughout all systems is mandatory. To get started, make sure that whatever endpoint you’re running the commands from has the PowerCLI module installed. If it isn’t installed, run the following command in an administrative PowerShell console:
Now we want to see a list of all the hosts we will change the Root password on. Type the following syntax to view a list of all ESXi hosts in vCenter:
Get-VMhost -Name *
Let’s create the password variables for the new credential and our current root credential. As shown in the image below, type the username as “root” and then set the password field to whatever your new password is going to be:
$NewPassword = Get-Credential $CurrentPassword = Get-Credential
Now it’s time for the magic one-liner, we will use the Set-VMHostAccount cmdlet to change the root password for all of our hosts to our $NewPassword variable:
ForEach($name in (Get-VMhost -name * ).name) { Connect-viserver -server $name -Credential $CurrentPassword -NotDefault; Set-VMHostAccount -server $name -UserAccount root -Password $NewPassword.GetNetworkCredential().Password}
We can see a connection establish between each ESXi host and the password is then changed:
Automating ESXi Password Rotations
Now, let’s take it a step further. In the past, I created an article on how to get started with automating KeePass. We will use the KeePass PowerShell module to store our ESXi password and create a scheduled task to rotate our ESXi passwords on schedule and update the KeePass database. I have created a KeePass database with the following folder structure.
Note: the script I will be sharing will rely on the title names being “ESXi” and “VCenter” as well as the location of these entries being at the root of the ESXi DB folder. You can always edit the script to change the folder locations and title names:
Now, I need to create an encrypted password file. This will allow me to safely store the KeePass database password on a network share and have my scheduled task run as an account that has access to that share. To set this up we just have to run the following syntax:
$Key = New-Object Byte[] 32 [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key) $Key | out-file "C:\Scripts\ESXi Pass Rotate\aes.key"
Next, we need to create our password file. Type in the following syntax, when prompted for credentials input your password to the KeePass database, the username field won’t matter:
(get-credential).Password | ConvertFrom-SecureString -key (get-content "C:\Scripts\ESXi Pass Rotate\aes.key") | set-content "C:\Scripts\ESXi Pass Rotate\password.txt"
Last but not least, we need to install the KeePass Powershell modules in order to manipulate KeePass. Open an administrative PowerShell console and type the following:
install-module -name PoShKeePass
Now, save the code to a .ps1 file. I’ve written a script that will take our password key, password file, and KeePass database and will automatically rotate the passwords on the ESXi hosts and save the new password to KeePass:
[CmdletBinding()] param( [Parameter(Mandatory=$True)] [String]$KeePassDB, [Parameter(Mandatory=$True)] [String]$Vcenter, [Parameter(Mandatory=$True,ParameterSetName="PassFile")] [String]$PasswordFile, [Parameter(Mandatory=$True,ParameterSetName="PassKey")] [String]$Passwordkey ) Begin{ #Retrive KeePass Password if -Passwordfile parameter is used if($PasswordFile -and $Passwordkey) { $KeePassPW = Get-Content $PasswordFile | ConvertTo-SecureString -Key (Get-Content $Passwordkey) } #Get current passwords for VCenter and ESXi New-KeePassDatabaseConfiguration -DatabaseProfileName 'ESXiAutoRotate' -DatabasePath $KeePassDB -UseMasterKey Try { $CurrentESxiPassword = (Get-KeePassEntry -DatabaseProfileName 'ESXiAutoRotate' -Title "ESXi" -WithCredential -MasterKey $KeePassPW ).password $currentVCenterPassword = (Get-KeePassEntry -DatabaseProfileName 'ESXiAutoRotate' -Title "VCenter" -WithCredential -MasterKey $KeePassPW ).password $currentVCenterUsername =(Get-KeePassEntry -DatabaseProfileName 'ESXiAutoRotate' -Title "VCenter" -WithCredential -MasterKey $KeePassPW ).username $VcenterCredential = New-Object System.Management.Automation.PsCredential($currentVCenterUsername,$currentVCenterPassword) $CurrentESXiCredential = New-Object System.Management.Automation.PsCredential("root",$CurrentESxiPassword) } Catch { Write-error -Message "Unable to retrieve credentials from $KeePassDB" } #Get the date for ESXi Password Title $timestamp = Get-Date -Format o | foreach {$_ -replace ":", "."} } Process{ #Autogenerate new credentials and create new entry in keepass New-KeePassEntry -DatabaseProfileName 'ESXiAutoRotate' -KeePassEntryGroupPath "ESXI DB" -Title "ESXi-New" -Notes "New auto rotate password on $timestamp" -UserName "root" -KeePassPassword $(New-KeePassPassword -UpperCase -LowerCase -Digits -SpecialCharacters -Length 10) -MasterKey $KeePasspw | Out-Null -ErrorAction SilentlyContinue $NewESxiPassword = (Get-KeePassEntry -DatabaseProfileName 'ESXiAutoRotate' -Title "ESXi-New" -WithCredential -MasterKey $KeePassPW ) #If new password is able to be generated, continue with password changes on ESXi environment if($NewESxiPassword) { #Get Connection to VCenter Connect-VIServer -Server $Vcenter -Credential $VcenterCredential #Change Password for all ESXi Hosts in VCenter ForEach($name in (Get-VMhost -name * ).name) { Connect-viserver -server $name -Credential $CurrentESXiCredential -NotDefault; Set-VMHostAccount -server $name -UserAccount root -Password $NewESxiPassword.Credential.GetNetworkCredential().password } } Else { Write-Error -Message "There was an issue with creating the new ESXi password" } } End { #clean up keepass Update-KeePassEntry -Title 'ESXi-Old' -KeePassEntry (Get-KeePassEntry -DatabaseProfileName 'ESXiAutoRotate' -Title "ESXi" -WithCredential -MasterKey $KeePassPW ) -DatabaseProfileName 'ESXiAutoRotate' -MasterKey $KeePassPW -KeePassEntryGroupPath "ESXI DB" -Force Update-KeePassEntry -Title 'ESXi' -KeePassEntry $NewESxiPassword -DatabaseProfileName 'ESXiAutoRotate' -MasterKey $KeePassPW -KeePassEntryGroupPath "ESXI DB" -Force Remove-KeePassDatabaseConfiguration -DatabaseProfileName 'ESXiAutoRotate' -Confirm:$false }
I have all my required files in a folder in C:\Scripts\ESXi Pass Rotate”:
To run the script, simply open up a PowerShell console and run the following syntax filling in the proper location of each file as necessary:
powershell -file "C:\Scripts\AutoRotatePassword.ps1" -keepassdb "C:\Scripts\ESXi Pass Rotate\ESXi DB.kdbx" -vcenter "192.168.0.7" -passwordfile "C:\Scripts\ESXi Pass Rotate\password.txt" -passwordkey "C:\Scripts\ESXi Pass Rotate\aes.key"
After the script has completed, we can see that our new password has been entered into KeePass and by testing our ESXi hosts we can see that the new password works:
This script can be run with Task Scheduler in order to perform automated monthly password rotations if required. Also, I highly recommend adding in some more “checks” and “logs” into the script in order to ensure an ESXi host that is having an issue with the password change will stand out for troubleshooting. The last thing you want is to have to recover the root password on the host because the password has been removed from KeePass. Being able to combine automated ESXi password changes with KeePass shows the real power of PowerShell modules in situations like this one.
Find this useful? Anything you’d like to see added? Let us know in the comments below!
Thanks for reading!
Want to do more with PowerShell? Learn how to use PowerShell to create your own ESXi Dashboard!
[the_ad id=”4738″][thrive_leads id=’18673′]
Not a DOJO Member yet?
Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!
10 thoughts on "How to Automate Root Password Rotations with PowerCLI"
Hi,
unfortunately, the script does not work.
I tried to setup the same file names and locations as described above.
powershell -file “C:\Scripts\AutoRotatePassword.ps1” -keepassdb “C:\Scripts\ESXi Pass Rotate\ESXi DB.kdbx” -vcenter “192.168.X.X” -passwordfile “C:\Scripts\ESXi Pass Rotate\password.txt” -passwordkey “C:\Scripts\ESXi Pass Rotate\aes.key”
I get the error:
powershell : C:\Scripts\AutoRotatePassword.ps1 : Parameter set cannot be resolved using the specified named parameters.
At line:3 char:1
+ powershell -file “C:\Scripts\AutoRotatePassword.ps1” -KeePassDB “C:\S …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (C:\Scripts\Auto…med parameters.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ CategoryInfo : InvalidArgument: (:) [AutoRotatePassword.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : AmbiguousParameterSet,AutoRotatePassword.ps1
Hi John, Can you try to remove the ParameterSetName= fields from the script’s parameters? Let me know if that solves it as it looks like it’s a problem with the parametersetnames. In the meantime I’ll check the script myself and update the article if necessary