PowerCLI: Multiple Virtual Machines Script

Overview

When I test for DISA STIG compliance, I see that they test an individual machine. I like to make a script that can test or add properties to multiple machines at a time; I find this is much more efficient.

Get a Secure Credential

The very first thing we need to do is open up a connection to the vCenter Appliance. I recommend using the fully qualified domain name, so in this post, I will be using vcsa.aaronrombaut.com. To get a secure credential, either with a user name and password, or with a smart card, use the following command:

$myCredential = Get-Credential

This should open up a Windows PowerShell credential request window.

This is what it will look like on the command line.

Make the Connection to a vCenter Server

Use the following command to make a connection to the vCenter Server.

Connect-VIServer -Server <vCenter-FQDN> -Credential $myCredential

If successful, the command line should return and a message indicating the connected server should display like in the image below.

Get a List of Virtual Machines

Now we want to get a list of all the virtual machines.

$myVirtualMachines = Get-VM 

We can see that this list includes the vSphere Cluster Services virtual machines, indicated by the names starting with the vCLS. We will want to exclude these virtual machines from our list so run this modified command.

$myVirtualMachines = Get-VM | Where-Object -Property Name -NotLike "vCLS*"

Build the Foreach Loop

Now, we just need a simple Foreach loop using the following syntax:

foreach ($<item> in $<collection>){<statement list>}

What this looks like on the command line with an advanced setting test.

Build Intelligence into the Foreach Loop

When implementing the text in the Fix Text section, some fixes require that if a setting exists, the value can be set. The alternative is when the setting does not already exist, the setting and value need to be added. See the following excerpt for details.

If the setting does not exist, run:

Get-VM “VM Name” | New-AdvancedSetting -Name isolation.tools.copy.disable -Value true

If the setting exists, run:

Get-VM “VM Name” | Get-AdvancedSetting -Name isolation.tools.copy.disable | Set-AdvancedSetting -Value true

We can see from the image that we will be prompted for every virtual machine where this is taking place. This is not going to work if we have more than a handful of machines, so I am going to modify the script slightly and add -Confirm:$false to the end of the line.

Now we can run the test again to verify that our Advanced Setting has been set.

The Full Scripts

There are two variables, here. One is the name of the Advanced Setting, to check or set, and the other is the value of the setting. This will allow for one off settings.

$advancedSettingName = "isolation.tools.copy.disable"
$advancedSettingValue = "true"

# Check if the setting exists
foreach ($myVirtualMachine in $myVirtualMachines) {
    if (Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $advancedSettingName) {
        Write-Host "Exists"
    } else {
        Write-Host "Does not exist"
    }
}

# Check for which logic works and modify setting as required
foreach ($myVirtualMachine in $myVirtualMachines) {
    if (Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $advancedSettingName) {
        Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $advancedSettingName | Set-AdvancedSetting -Value $advancedSettingValue -Confirm:$false
    } else {
        Get-VM $myVirtualMachine | New-AdvancedSetting -Name $advancedSettingName -Value $advancedSettingValue -Confirm:$false
    }
}

# Check for setting again -- should result in "Exists"
foreach ($myVirtualMachine in $myVirtualMachines) {
    if (Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $advancedSettingName) {
        Write-Host "Exists"
    } else {
        Write-Host "Does not exist"
    }
} 

The next script will provide a means to set multiple settings and values in one. This script uses a PowerShell Hash Table. The script iterates over each setting and then all the virtual machines before moving on to the next setting.

# Various STIG Settings to Check
$advancedSettings = @{}
$advancedSettings.Add("isolation.tools.copy.disable", "true")               # VMCH-70-000001
$advancedSettings.Add("isolation.tools.dnd.disable", "true")                # VMCH-70-000002
$advancedSettings.Add("isolation.tools.paste.disable","true")               # VMCH-70-000003
$advancedSettings.Add("isolation.tools.diskShrink.disable","true")          # VMCH-70-000004
$advancedSettings.Add("isolation.tools.diskWiper.disable","true")           # VMCH-70-000005
$advancedSettings.Add("isolation.tools.hgfsServerSet.disable","true")       # VMCH-70-000007
$advancedSettings.Add("RemoteDisplay.maxConnections","1")                   # VMCH-70-000013
$advancedSettings.Add("tools.setinfo.sizeLimit","1048576")                  # VMCH-70-000015
$advancedSettings.Add("isolation.device.connectable.disable","true")        # VMCH-70-000016
$advancedSettings.Add("tools.guestlib.enableHostInfo","false")              # VMCH-70-000017
$advancedSettings.Add("tools.guest.desktop.autolock","true")                # VMCH-70-000022
$advancedSettings.Add("mks.enable3d","false")                               # VMCH-70-000023
$advancedSettings.Add("log.rotateSize","2048000")                           # VMCH-70-000026
$advancedSettings.Add("log.keepOld","10")                                   # VMCH-70-000027

$advancedSettings.keys | ForEach-Object {
    # Check if the setting exists
    foreach ($myVirtualMachine in $myVirtualMachines) {
        if (Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $_) {
            Write-Output "Advanced setting $_ exists!"
        }
        else {
            Write-Output "Advanced setting $_ does not exist!"
        }
    }
}

$advancedSettings.keys | ForEach-Object {
    # Check for which logic works and modify setting as required
    foreach ($myVirtualMachine in $myVirtualMachines) {
        if (Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $_) {
            Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $_ | Set-AdvancedSetting -Value $($advancedSettings[$_]) -Confirm:$false
        }
        else {
            Get-VM $myVirtualMachine | New-AdvancedSetting -Name $_ -Value $($advancedSettings[$_]) -Confirm:$false
        }
    }
}

$advancedSettings.keys | ForEach-Object {
    # Check if the setting exists
    foreach ($myVirtualMachine in $myVirtualMachines) {
        if (Get-VM $myVirtualMachine | Get-AdvancedSetting -Name $_) {
            Write-Output "Advanced setting $_ exists!"
        }
        else {
            Write-Output "Advanced setting $_ does not exist!"
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *