Home > Blogs > VMware PowerCLI Blog > Monthly Archives: May 2012

Monthly Archives: May 2012

Automating SSL Checks for vCenter and Host Certificates

AlanFeb2012_thumb_thumb1_thumb_thumb[2]
Posted by
Alan Renouf
Technical Marketing

Recently William Lam wrote a great article showing how easy it was to check your hosts SSL Certificates and Expiry information using a free tool called ssl-cert-check, he explains that it is best practice to replace VMware’s self-signed SSL certificates that are included with the vCenter Server and on all hosts, make sure you read his post here and in turn make sure you also read Michael Websters articles which take you through this process here.

But what if we wanted to check these certificates in PowerCLI, recently I found a great PowerShell Advanced function which allows us to do just this, we are able to test the certificate of any given website and return the details.

Using this script and a little code of our own we can easily check all our hosts and the vCenter Certificates as seen below:

SNAGHTML1f5e280e

The code will output the most important details included who the issuer of the certificate is, whether it is valid and when it expires, both in date and length of time.

This could easily be adapted to check on a regular basis and email closer to the expiry date.

Code

Function Test-WebServerSSL {
# Function original location:
http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?List=332991f0-bfed-4143-9eea-f521167d287c&ID=60
[CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
        [string]$URL,
        [Parameter(Position = 1)]
        [ValidateRange(1,65535)]
        [int]$Port = 443,
        [Parameter(Position = 2)]
        [Net.WebProxy]$Proxy,
        [Parameter(Position = 3)]
        [int]$Timeout = 15000,
        [switch]$UseUserContext
    )
Add-Type @"
using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
namespace PKI {
    namespace Web {
        public class WebSSL {
            public Uri OriginalURi;
            public Uri ReturnedURi;
            public X509Certificate2 Certificate;
            //public X500DistinguishedName Issuer;
            //public X500DistinguishedName Subject;
            public string Issuer;
            public string Subject;
            public string[] SubjectAlternativeNames;
            public bool CertificateIsValid;
            //public X509ChainStatus[] ErrorInformation;
            public string[] ErrorInformation;
            public HttpWebResponse Response;
        }
    }
}
"@
    $ConnectString = "
https://$url:$port"
    $WebRequest = [Net.WebRequest]::Create($ConnectString)
    $WebRequest.Proxy = $Proxy
    $WebRequest.Credentials = $null
    $WebRequest.Timeout = $Timeout
    $WebRequest.AllowAutoRedirect = $true
    [Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
    try {$Response = $WebRequest.GetResponse()}
    catch {}
    if ($WebRequest.ServicePoint.Certificate -ne $null) {
        $Cert = [Security.Cryptography.X509Certificates.X509Certificate2]$WebRequest.ServicePoint.Certificate.Handle
        try {$SAN = ($Cert.Extensions | Where-Object {$_.Oid.Value -eq "2.5.29.17"}).Format(0) -split ", "}
        catch {$SAN = $null}
        $chain = New-Object Security.Cryptography.X509Certificates.X509Chain -ArgumentList (!$UseUserContext)
        [void]$chain.ChainPolicy.ApplicationPolicy.Add("1.3.6.1.5.5.7.3.1")
        $Status = $chain.Build($Cert)
        New-Object PKI.Web.WebSSL -Property @{
            OriginalUri = $ConnectString;
            ReturnedUri = $Response.ResponseUri;
            Certificate = $WebRequest.ServicePoint.Certificate;
            Issuer = $WebRequest.ServicePoint.Certificate.Issuer;
            Subject = $WebRequest.ServicePoint.Certificate.Subject;
            SubjectAlternativeNames = $SAN;
            CertificateIsValid = $Status;
            Response = $Response;
            ErrorInformation = $chain.ChainStatus | ForEach-Object {$_.Status}
        }
        $chain.Reset()
        [Net.ServicePointManager]::ServerCertificateValidationCallback = $null
    } else {
        Write-Error $Error[0]
    }
}

Connect-VIServer MyVC -User Administrator –Password Password!

# Check for Host Certificates
Get-VMHost | Foreach { Test-WebServerSSL -URL $_.Name | Select OriginalURi, CertificateIsValid, Issuer, @{N="Expires";E={$_.Certificate.NotAfter} }, @{N="DaysTillExpire";E={(New-TimeSpan -Start (Get-Date) -End ($_.Certificate.NotAfter)).Days} }}

# Check for vCenter Certificate
Test-WebServerSSL -URL $DefaultVIServer | Select OriginalURi, CertificateIsValid, Issuer, @{N="Expires";E={$_.Certificate.NotAfter} }, @{N="DaysTillExpire";E={(New-TimeSpan -Start (Get-Date) -End ($_.Certificate.NotAfter)).Days} }

Get notification of new blog postings and more by following VMware PowerCLI on Twitter: @PowerCLI

 

Retrieving License keys from Multiple vCenters

AlanFeb2012_thumb_thumb1_thumb_thumb[1]
Posted by
Alan Renouf
Technical Marketing

A question I receive all the time is:

How can I list all license keys I have for all of my Virtual Centers in my Infrastructure ?

 

Luckily PowerCLI enables us to work with multiple vCenters all at one, we can connect to many vCenters or hosts and pull back information on all of these at the same time, to do this you need to set the PowerCLI Configuration to work in multiple mode and then you can connect to more than one vCenter at the same time, to do this see the following example:

SNAGHTMLc8e21f3

Once we are in multiple configuration mode we can then use Connect-VIserver on as many vCenters or hosts as you like, we can use this to connect to multiple vCenters with the same credentials or just list each one like below:

Connect to multiple vCenters with the same username and password:

Connect-VIServer VC1, VC2, VC3, VC4 –User Administrator –Password MyPa$$word

Connect to multiple vCenters with different credentials:

Connect-VIServer VC1 –User Administrator1 –Password MyPa$$word1

Connect-VIServer  VC2 –User Administrator2 –Password MyPa$$word2

Connect-VIServer VC3 –User Administrator3 –Password MyPa$$word3

Connect-VIServer VC4 –User Administrator4 –Password MyPa$$word4

Once connected this information is stored in the $DefaultVIServers variable, this can easily be viewed at any time:

SNAGHTMLc96fa66

We are also easily able to run scripts against these connections, like for example the License script at the end of this post, this lists all license keys and their information for each vCenter:

(You will excuse me if I exclude the actual key)

SNAGHTMLcc99b96

The Code

# Set to multiple VC Mode
if(((Get-PowerCLIConfiguration).DefaultVIServerMode) -ne "Multiple") {
    Set-PowerCLIConfiguration -DefaultVIServerMode Multiple | Out-Null
}

# Make sure you connect to your VCs here

# Get the license info from each VC in turn
$vSphereLicInfo = @()
$ServiceInstance = Get-View ServiceInstance
Foreach ($LicenseMan in Get-View ($ServiceInstance | Select -First 1).Content.LicenseManager) {
    Foreach ($License in ($LicenseMan | Select -ExpandProperty Licenses)) {
        $Details = "" |Select VC, Name, Key, Total, Used, ExpirationDate , Information
        $Details.VC = ([Uri]$LicenseMan.Client.ServiceUrl).Host
        $Details.Name= $License.Name
        $Details.Key= $License.LicenseKey
        $Details.Total= $License.Total
        $Details.Used= $License.Used
        $Details.Information= $License.Labels | Select -expand Value
        $Details.ExpirationDate = $License.Properties | Where { $_.key -eq "expirationDate" } | Select -ExpandProperty Value
        $vSphereLicInfo += $Details
    }
}
$vSphereLicInfo | Format-Table -AutoSize

 

Get notification of new blog postings and more by following VMware PowerCLI on Twitter: @PowerCLI

Working with VM Devices in PowerCLI

AlanFeb2012_thumb_thumb1_thumb_thumb[2]
Posted by
Alan Renouf
Technical Marketing

Recently I was asked if it was possible to list all VMs which had particular devices attached to them, and further to this, was there any way to remove the device from the VM or multiple VMs on mass.

To address this question lets look at the types of devices which can be used by a VM:

image

Some of these devices are more popular than others, most VMs will have a Hard Disk and an Ethernet Adapter but I rarely see a VM with a Parallel or Serial port, so lets see which of these items we support out of the box in PowerCLI.

Floppy Drives CD/DVD Drive USB Device Ethernet Adapter Hard Disk SCSI Device

Get-FloppyDrive
New-FloppyDrive
Remove-FloppyDrive
Set-FloppyDrive

Get-CDDrive
New-CDDrive
Remove-CDDrive
Set-CDDrive

Get-USBDevice
Remove-USBDevice

Get-NetworkAdapter
New-NetworkAdapter
Remove-NetworkAdapter
Set-NetworkAdapter

Copy-HardDisk
Get-HardDisk
New-HardDisk
Remove-HardDisk
Set-HardDisk

Get-ScsiController
New-ScsiController
Set-ScsiController

 

Using Device cmdlets

Lets take a look at the Floppy Drive cmdlets and how we might use these, starting with a list of our VMs which have a Floppy Drive attached, in this case I am showing my DemoVMs and their floppy details:

SNAGHTML57bc10a

We can also easily disconnect a floppy drive as seen below:

SNAGHTML57e7e30

And remember, this can be done for all virtual machines not just one. So what if we didn’t want the floppy drives at all, I mean how often do you use a floppy drive?

SNAGHTML5809b70

Notice the first VM gave us an error, this is of course because it was powered on, just as with the vSphere Client we must Power Off the VM before removing Floppy Drives.  You can see from the screenshot above that the floppy drives have been removed from our other machines, this can of course be confirmed by looking within the vSphere client.

What about the other devices ?

We have covered Floppy Drives in the above example but the other devices which have cmdlets will work in a similar way, remember if you cant work it out Get-Help is your friend, examples from any of the PowerCLI or PowerShell cmdlets can be seen by simply using Get-Help as below:

SNAGHTML586cccd

But what about the devices which don’t have cmdlets to work with them, what if you had a serial port or parallel port you wanted to remove on mass, I have seen this before when people have converted their physical hosts to virtual machines, sometimes they have not removed the serial and parallel ports which are no longer needed by the VMs.

We can use PowerCLI to look further into our VM objects and see which hardware devices are present on a virtual machine with a single line of code:

SNAGHTML59028f0

As you can see from the above example, each of the hardware devices listed under the Config.Hardware part of the virtual machine has a different type, and in this list we can see both the SerialPort and ParallelPort types.  Using this we can easily create some advanced functions which allow us to work with these devices.

Once the code at the bottom of this post is imported into our session we can list the serial ports attached to our virtual machines and also the parallel ports attached like so:

SNAGHTML5958c25

And of course we can remove these on mass as well by using the following:

SNAGHTML59764a8

Serial/Parallel port management scripts

Copy and paste the following code into your PowerCLI Console or PowerShell editor and run them to help you work with Serial and Parallel ports on mass.

Function Get-SerialPort {
    Param (
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
        $VM
    )
    Process {
        Foreach ($VMachine in $VM) {
            Foreach ($Device in $VMachine.ExtensionData.Config.Hardware.Device) {
                If ($Device.gettype().Name -eq "VirtualSerialPort"){
                    $Details = New-Object PsObject
                    $Details | Add-Member Noteproperty VM -Value $VMachine
                    $Details | Add-Member Noteproperty Name -Value $Device.DeviceInfo.Label
                    If ($Device.Backing.FileName) { $Details | Add-Member Noteproperty Filename -Value $Device.Backing.FileName }
                    If ($Device.Backing.Datastore) { $Details | Add-Member Noteproperty Datastore -Value $Device.Backing.Datastore }
                    If ($Device.Backing.DeviceName) { $Details | Add-Member Noteproperty DeviceName -Value $Device.Backing.DeviceName }
                    $Details | Add-Member Noteproperty Connected -Value $Device.Connectable.Connected
                    $Details | Add-Member Noteproperty StartConnected -Value $Device.Connectable.StartConnected
                    $Details
                }
            }
        }
    }
}

Function Remove-SerialPort {
    Param (
        [Parameter(Mandatory=$True,ValueFromPipelinebyPropertyName=$True)]
        $VM,
        [Parameter(Mandatory=$True,ValueFromPipelinebyPropertyName=$True)]
        $Name
    )
    Process {
        $VMSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $VMSpec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec
        $VMSpec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec
        $VMSpec.deviceChange[0].operation = "remove"
        $Device = $VM.ExtensionData.Config.Hardware.Device | Foreach {
            $_ | Where {$_.gettype().Name -eq "VirtualSerialPort"} | Where { $_.DeviceInfo.Label -eq $Name }
        }
        $VMSpec.deviceChange[0].device = $Device
        $VM.ExtensionData.ReconfigVM_Task($VMSpec)
    }
}

Function Get-ParallelPort {
    Param (
        [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
        $VM
    )
    Process {
        Foreach ($VMachine in $VM) {
            Foreach ($Device in $VMachine.ExtensionData.Config.Hardware.Device) {
                If ($Device.gettype().Name -eq "VirtualParallelPort"){
                    $Details = New-Object PsObject
                    $Details | Add-Member Noteproperty VM -Value $VMachine
                    $Details | Add-Member Noteproperty Name -Value $Device.DeviceInfo.Label
                    If ($Device.Backing.FileName) { $Details | Add-Member Noteproperty Filename -Value $Device.Backing.FileName }
                    If ($Device.Backing.Datastore) { $Details | Add-Member Noteproperty Datastore -Value $Device.Backing.Datastore }
                    If ($Device.Backing.DeviceName) { $Details | Add-Member Noteproperty DeviceName -Value $Device.Backing.DeviceName }
                    $Details | Add-Member Noteproperty Connected -Value $Device.Connectable.Connected
                    $Details | Add-Member Noteproperty StartConnected -Value $Device.Connectable.StartConnected
                    $Details
                }
            }
        }
    }
}

Function Remove-ParallelPort {
    Param (
        [Parameter(Mandatory=$True,ValueFromPipelinebyPropertyName=$True)]
        $VM,
        [Parameter(Mandatory=$True,ValueFromPipelinebyPropertyName=$True)]
        $Name
    )
    Process {
        $VMSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
        $VMSpec.deviceChange = New-Object VMware.Vim.VirtualDeviceConfigSpec
        $VMSpec.deviceChange[0] = New-Object VMware.Vim.VirtualDeviceConfigSpec
        $VMSpec.deviceChange[0].operation = "remove"
        $Device = $VM.ExtensionData.Config.Hardware.Device | Foreach {
            $_ | Where {$_.gettype().Name -eq "VirtualParallelPort"} | Where { $_.DeviceInfo.Label -eq $Name }
        }
        $VMSpec.deviceChange[0].device = $Device
        $VM.ExtensionData.ReconfigVM_Task($VMSpec)
    }
}

 

Get notification of new blog postings and more by following VMware PowerCLI on Twitter: @PowerCLI