Over the past year I have seen quite a few STS certs expire in production environments. I have been meaning to write something to scan a VCSA and report back the expiry dates of all the certs.
This has posed a problem because I have to use SSH and one command needs to follow another. In the end I discovered the SSHShellStream in the Posh-SSH module. I will document that (character building) journey in another post.
This script will use the POSH-SSH module to connect to a VCSA and issue a one liner BASH script to get the cert info. This info is captured and processed by the script. But the STS cert info can not be captured in this way as it requires a python script to be uploaded and run. This script needs to be manually copied to the remote VCSA.
Deployment of the script
- You will need the POSH-SSH module installed.
- You will need to copy up the stscheck.ph script to the /tmp directory of the VCSA
The checksts.py script is located here
My Local copy
vmware KB - Set the $vcsa variable to the FQDN of your vCenter.
Thats it. you are ready to go.
Running the script
- The script will connect to $vcsa using SSH and prompt for credentials.
- Once the script has run you will have an array called $CertReport and a copy of that in c:\temp\CertReport.csv
You will end up with a CSV file looking very much like this.
"vCenter","location","Name","ExpDate","Days"
"myvCenter.mydomain.com","lab","STORE MACHINE_SSL_CERT","15/03/2023 13:27:50","716"
"myvCenter.mydomain.com","lab","STORE TRUSTED_ROOTS","09/03/2031 13:27:50","3633"
"myvCenter.mydomain.com","lab","STORE TRUSTED_ROOTS","07/01/2029 13:27:50","2841"
"myvCenter.mydomain.com","lab","STORE TRUSTED_ROOTS","08/01/2031 13:27:50","3573"
"myvCenter.mydomain.com","lab","STORE TRUSTED_ROOTS","08/01/2031 13:27:50","3573"
"myvCenter.mydomain.com","lab","STORE TRUSTED_ROOTS","09/03/2031 13:27:50","3633"
"myvCenter.mydomain.com","lab","STORE machine","09/03/2031 13:27:50","3632"
"myvCenter.mydomain.com","lab","STORE vsphere-webclient","09/03/2031 13:27:50","3633"
"myvCenter.mydomain.com","lab","STORE vpxd","09/03/2031 13:27:50","3633"
"myvCenter.mydomain.com","lab","STORE vpxd-extension","09/03/2031 13:27:50","3633"
"myvCenter.mydomain.com","lab","STORE hvc","09/03/2031 13:27:50","3632"
"myvCenter.mydomain.com","lab","STORE data-encipherment","09/03/2031 13:27:50","3633"
"myvCenter.mydomain.com","lab","STORE SMS","14/03/2031 13:27:50","3638"
"myvCenter.mydomain.com","lab","STORE wcp","14/03/2023 13:27:50","716"
"myvCenter.mydomain.com","lab","STS Valid LEAF","13/01/2023 13:27:50","656"
"myvCenter.mydomain.com","lab","STS Valid Root","08/01/2031 13:27:50","3573"
Note: that the above output is from a VCSA server installed about 2 weeks ago, so All is looking good. I do not have any samples of an expired certificate (Ill update this post in 716 days) so I do not know how the script will deal with an expired Cert. But saying that, my On-call week is about to start so I may get an example. Im “lucky” like that.
Anyhow, here is the script
import-module posh-ssh
$Cred = Get-Credential
$vcsa = 'MyvCenterServer.Domain.com'
$location = 'HomeLab'
# connect to vcsa with SSH and open the SSh stream
$session = New-SSHSession -ComputerName $vcsa -Credential $cred –AcceptKey
$stream = New-SSHShellStream -SSHSession $session -TerminalName tty
# send the commands and get the results in to $CertList and $STSCertList
# drop to the BASH shell
$stream.WriteLine('shell')
sleep 3
# send a BASH one liner to list the crets and there info
$stream.WriteLine('for i in $(/usr/lib/vmware-vmafd/bin/vecs-cli store list); do echo STORE $i; sudo /usr/lib/vmware-vmafd/bin/vecs-cli entry list --store $i --text | egrep "Alias|Not After"; done')
sleep 3
# read the result of that in to the variable $CertList
$CertList = $stream.Read()
sleep 3
$stream.WriteLine('cd /tmp')
sleep 3
$DontCare = $stream.Read()
sleep 3
# run the checksys python script in /tmp (if that is where you have deployed it to)
$stream.WriteLine('python checksts.py')
sleep 3
# get the output of that script in to the $STSCertList variable
$STSCertList = $stream.Read()
# close the SSH session and stream
$stream.Close()
Remove-SSHSession -SSHSession $session | Out-Null
# $CertList and $STSCertList are txt streams, split using newline to get an array of text lines (a text file)
$NewCertList = $CertList.split([Environment]::NewLine)
$NewSTSCertList = $STSCertList.split([Environment]::NewLine)
# loop through each line and put the relivent info in to the $CertReport array
$CertReport = @()
foreach($line in $NewCertList)
{
if ($line -match "STORE"){$CurrentStore = $line}
if (($Line -match "not After") -and ($Line -notmatch "egrep"))
{
$line = $line.replace("Not After :","")
$line = $line.replace(" "," ")
$line = $line.replace(" GMT"," ")
$line = $line.trim()
$cells = $line.split(" ")
if ($cells[0] -eq "Jan"){$Month = 1}
if ($cells[0] -eq "Feb"){$Month = 2}
if ($cells[0] -eq "Mar"){$Month = 3}
if ($cells[0] -eq "Apr"){$Month = 4}
if ($cells[0] -eq "May"){$Month = 5}
if ($cells[0] -eq "Jun"){$Month = 6}
if ($cells[0] -eq "Jul"){$Month = 7}
if ($cells[0] -eq "Aug"){$Month = 8}
if ($cells[0] -eq "Sep"){$Month = 9}
if ($cells[0] -eq "Oct"){$Month = 10}
if ($cells[0] -eq "Nov"){$Month = 11}
if ($cells[0] -eq "Dec"){$Month = 12}
# get the exp date and convert to a date-time object
$day = $Cells[1]
$year = $cells[3]
$ExpDate = get-date -year $year -month $Month -day $day
# now get the number of days to cert expire
$ExpIn = $ExpDate - (get-date)
# create a tmp object with cert info and add to th result array, $CertReport
$tmpInfo = '' | select vCenter,location,Name,ExpDate,Days
$tmpInfo.vCenter = $vcsa
$tmpInfo.location = $location
$tmpInfo.Name = $CurrentStore
$tmpInfo.ExpDate = $ExpDate
$tmpInfo.Days = $ExpIn.days
$CertReport += $tmpInfo
}
}
foreach($line in $NewSTSCertList)
{
if($line -match "VALID CERTS"){$CertValid = "Valid"}
if($line -match "EXPIRED CERTSS"){$CertValid = "Expired"}
if($line -match "LEAF CERTS"){$CertType = "LEAF"}
if($line -match "Root CERTS"){$CertType = "Root"}
if($line -match "Certificate")
{
# split the line using a space as the delimiter
$cells = $line.split(" ")
$CellNum = 0
# loop through the cells, if the cell = "days" get the cell before it as that is the number
foreach ($Cell in $cells)
{
if ($cell -eq "days"){$ExpDays = $Cells[$CellNum - 1] }
$CellNum ++
}
# create a tmp object with cert info and add to th result array, $CertReport
$tmpInfo = '' | select vCenter,location,Name,ExpDate,Days
$tmpInfo.vCenter = $vcsa
$tmpInfo.location = $location
$tmpInfo.Name = "STS " + $CertValid + " " + $CertType
$tmpInfo.ExpDate = (get-date).adddays([int]$ExpDays)
$tmpInfo.Days = $ExpDays
$CertReport += $tmpInfo
}
}
$CertReport | export-csv "C:\temp\certReport.csv" -NoTypeInformation
You cannot call a method on a null-valued expression.
At line:3 char:1
+ $NewCertList = $CertList.split([Environment]::NewLine)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At line:4 char:1
+ $NewSTSCertList = $STSCertList.split([Environment]::NewLine)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Looks like the $STSCertList is empty. did you connect to the vCenter?
New-SSHSession : An existing connection was forcibly closed by the remote host
At line:8 char:12
+ $session = New-SSHSession -ComputerName $vcsa -Credential $cred –Acce …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (Renci.SshNet.SshClient:SshClient) [New-SSHSession], SshConne
ctionException
+ FullyQualifiedErrorId : SSH.NewSshSession
New-SSHShellStream : Cannot bind argument to parameter ‘SSHSession’ because it is null.
At line:9 char:42
+ $stream = New-SSHShellStream -SSHSession $session -TerminalName tty
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [New-SSHShellStream], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,New-SSHShellStream
can you SSH to your vcentrer?
if so, try updating the posh-ssh module