Scripting Corner: Send Commands as a root via SSH to ESXi with permit root login disabled.

Once upon a time when I wanted to remove many datastores from many hosts in the process of their decomission after consolidation, I was struck by an issue that can be found at VMware’s KB Article 2011220. The file used by SIOC was locked and because of that the datastore couldn’t be removed. To resolve this issue I would have to visit some 20 hosts via PuTTy and restart the StorageRM service. This seemed as a pretty tedious thing to do one-by-one, so I took the scripting approach 🙂

The only magic of this script lies in piping the root’s password in the plaintext (never visible to the user, but I guess this is not the maximum-security-best-practice) to the su -c command, which is will query you for the root password and then do a single command after successful authentication. You will need the plink utility to be able to send the commands via SSH.

For this script to work you will need to have an AD authentication to your ESXi host as well as the root password. What it basically does is retrieving a list of ESXi hosts from a text file, turning on SSH and disabling Lockdown Mode, runs the plink utility and then running a one-liner command with root privileges found inside the $runssh variable. Don’t worry about the last few lines being blue (aka commented) starting from line 71 – the crazy quotation is there to enable the root command’s execution. I let my own command /etc/init.d/storageRM start there so you can see the whole syntax.

function ESXSvc ($command, $service, $inESX)
{
 #Function starts here
 # Check if the service is running...
 $running = Get-VMHostService -VMHost $inESX | Where { $_.Key -eq "$service" } | Select -ExpandProperty Running

 If ($command -eq "start")
 {
 If ($running -eq $false)
 {
 Write-Host "Starting $service Service on $inESX"
 Get-VMHostService -VMHost $inESX | Where { $_.Key -eq "$service" } | Start-VMHostService -Confirm:$false | Out-Null
 }
 ELSE
 {
 Write-Host "The $service Service is already running on $inESX"
 }
 }
 ElseIf ($command -eq "stop")
 {
 If ($running -eq $true)
 {
 Write-Host "Stopping $service Service on $inESX"
 Get-VMHostService -VMHost $inESX | Where { $_.Key -eq “$service” } | Stop-VMHostService -Confirm:$false | Out-Null
 }
 Else
 {
 Write-Host "The $service Service is already stopped on $inESX"
 }
 }
} # Function ends here

$sshsvc = 'TSM-SSH'

Write-Host "--- ESXi Root Commands Probe ---`nUse to run as a root on a single or many ESXi hosts remotely `n" -ForegroundColor Green

# set variables for SCP transfer
$termapp = '.\plink.exe'
$esxilist = Get-Content esxi.txt

# Define username to be used for pushing the file via SCP, the user must be able to access the ESXi host with these credentials
$scpuser = Read-Host 'Enter your superuser account credentials in domain\user format'
$scppwd = Read-Host 'Enter your superuser password' -AsSecureString
$rootpw = Read-Host 'Enter ther Root Password for ESXi' -AsSecureString

ForEach ($esxi in $esxilist)
{
 Write-Host `n

 # Convert SecureStrings to plain password
 $BSTR0 = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($scppwd)
 $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR0)
 $BSTR1 = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($rootpw)
 $PlainRootPw = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR1)

 Write-Host "********** Initiating connection to" $esxi "**********"`n -ForegroundColor 'Yellow'

 # Start SSH and Exit Lockdown mode...
 ESXSvc "start" $sshsvc $esxi
 write-host "Exitting Lockdown Mode"
 (Get-VMhost $esxi | Get-View).ExitLockdownMode() | Out-Null

 Write-Host "Storing RSA key in the host cache..." $esxi -ForegroundColor Green
 # If the host's key has not been cached before, send a "yes" before performing a blank function inside the session.
 $runssh = "cmd /c echo y | $termapp -pw $PlainPassword $scpuser`@$esxi exit"
 Invoke-Expression $runssh | Out-Null

 Write-Host "Running the command! `n" -ForegroundColor green
 # Enter your command you want to run as root in $shellcmd
 $shellcmd = "/etc/init.d/storageRM start"
 $cmd = "echo $plainrootpw | su -c `'$shellcmd`' "
 $runssh = "$termapp -pw $PlainPassword $scpuser`@$esxi `"$cmd`""
 Invoke-Expression $runssh 

 #Reset the converted password string to NULL
 $PlainPassword = $null
 $PlainRootPw = $null

 # Stop SSH and Enter Lockdown mode...
 ESXSvc "stop" $sshsvc $esxi
 Write-Host "Entering Lockdown Mode"
 (get-vmhost $esxi | get-view).EnterLockdownMode() | Out-Null

 Write-Host "********** Disconnected from" $esxi "**********" `n -ForegroundColor 'Yellow'

}

I hope this helped some of you to tackle an issue that needs root privileges and needs to be run at several hosts.

Advertisements

2 thoughts on “Scripting Corner: Send Commands as a root via SSH to ESXi with permit root login disabled.

  1. fleet maintenance software

    Hi there very cool website!! Guy .. Beautiful .. Wonderful ..
    I’ll bookmark your website and take the feeds also? I’m glad to search out a lot of useful information right here in the
    post, we want develop extra techniques in this regard, thank you for sharing.
    . . . . .

    Reply
    1. Ali Post author

      Thank you very much for the feedback, I’ll be glad if you stop by once in a while to see what I have been up to 🙂

      Reply

Share your thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s