So my customer asked for a solution to add local users on ESXi hosts that are in lockdown mode. A side quest was to add these to the lockdown exception list. The use case for this is app volumes, they want to be able to keep using them in case the vCenter server goes down. The trick to this that you need to talk to two different viserver entities. The vCenter server and the local ESXi host since you can add those users via vCenter.

Offcourse PowerCLI to the rescue! I decided to do everything in a try catch construction for some error handling and to give some visual output. These cab be stripped if you want but i like some feedback.

Some of the outtakes:

(get-vmhost $vmhost | get-view).ExitLockdownMode() (get-vmhost $vmhost | get-view).EnterLockdownMode()

These two disable and enable the current lockdown mode, this is necessary before being able to create the local user.

Try { $account = Get-VMHostAccount -server $vmhost.name -Id $accountName -ErrorAction Stop | Set-VMHostAccount -server $vmhost.name -Password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($accountPswd))) -Description $accountDescription } Catch { $account = New-VMHostAccount -server $vmhost.name -Id $accountName -Password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($accountPswd))) -Description $accountDescription -UserAccount -GrantShellAccess }

Some encryption stuff in here but that’s because I dislike having password visible as plain tekst. This first test if the account exists and then sets the password and description. If the user doesn’t exist it will create the user for you.

$rootFolder = Get-Folder -server $vmhost.name -Name ha-folder-root New-VIPermission -server $vmhost.name -Entity $rootFolder -Principal $account -Role admin

This gives the newly created or edited user the admin role. If you want to use a custom role this could be added to the script, we decided to go for the admin role since app volumes needs an awful lot of rights anyway. In that case i would recommend to use a variable for role name and create it per host using new-VIrole

$HostAccessManager = Get-View -Server $vCenter $vmhost.ExtensionData.ConfigManager.HostAccessManager $HostAccessManager.UpdateLockdownExceptions($accountName)

This simply adds the user to the lockdown exception list.

So now the complete script:

#------------------------------------------------- # Create local ESXi user with admin rights and lockdown exception while the host is in lockdown mode # # Requires PowerCLI 6.5 or higher (module based not snappin) # Based on scripts by Luc Dekens and others # # Version 1.0 # 09-10-2017 # Created by: Wouter Kursten # #------------------------------------------------- # # Load the required VMware modules (for PowerShell only) Write-Host "Loading VMware PowerCLI Modules" -ForegroundColor Green try { get-module -listavailable vm* | import-module -erroraction stop } catch { write-host "No Powercli found" -ForegroundColor Red } #Ask for connection information $vcenter=Read-Host "Enter vCenter server name" $Target = Read-Host "Which hosts? (i.e. server*)" $rootpassword = Read-Host "Enter root Password" -AsSecureString $accountName = $userPassword = Read-Host "Enter New Username" $accountDescription = $userPassword = Read-Host "Enter New User description" $accountPswd = Read-Host "Enter New User Password" -AsSecureString $rootuser="root" # Connect to vCenter $connectedvCenter = $global:DefaultVIServer if($connectedvCenter.name -ne $vcenter){ Connect-VIServer $vCenter -wa 0 | Out-Null Write-Host "Connected" Write-Host " " } # Get the host inventory from vCenter $vmhosts = Get-VMHost $Target | Sort Name foreach($vmhost in $vmhosts){ try { (get-vmhost $vmhost | get-view).ExitLockdownMode() write-host "Lockdown disabled for $vmhost" -foregroundcolor green } catch { write-host "can't disable lockdown for $vmhost maybe it's already disabled" -foregroundcolor Red } connect-viserver -server $vmhost -user $rootuser -password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($rootpassword))) -wa 0 -notdefault | Out-Null Try { $account = Get-VMHostAccount -server $vmhost.name -Id $accountName -ErrorAction Stop | Set-VMHostAccount -server $vmhost.name -Password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($accountPswd))) -Description $accountDescription } Catch { $account = New-VMHostAccount -server $vmhost.name -Id $accountName -Password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($accountPswd))) -Description $accountDescription -UserAccount -GrantShellAccess } $rootFolder = Get-Folder -server $vmhost.name -Name ha-folder-root New-VIPermission -server $vmhost.name -Entity $rootFolder -Principal $account -Role admin #Adding the new user to the Lockdown Exceptions list $HostAccessManager = Get-View -Server $vCenter $vmhost.ExtensionData.ConfigManager.HostAccessManager $HostAccessManager.UpdateLockdownExceptions($accountName) Disconnect-VIServer $vmhost.name -Confirm:$false try { (get-vmhost $vmhost | get-view).EnterLockdownMode() write-host "Lockdown enabled for $vmhost" -foregroundcolor green } catch { write-host "can't disable lockdown for $vmhost maybe it's already Enabled?" -foregroundcolor Red} } } Disconnect-VIServer -Confirm:$false

Future versions of this script will not be edited on here so always check the latest version on github.