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.
The optimal way to address this is to have a dedicated workstation or server in the data center that you can log into with PowerShell and PowerCLI installed. Since you are hopefully logging in with your administrator token and your administrator account has either been given permission directly on vSphere or through a security group, then you should be able to just log into the server when you try to use Connect-VIServer (https://vdc-repo.vmware.com/vmwb-repository/dcr-public/85a74cac-7b7b-45b0-b850-00ca08d1f238/ae65ebd9-158b-4f31-aa9c-4bbdc724cc38/doc/Connect-VIServer.html). The credential of the currently logged on user, that’s you, will get passed along with the request.
$VIRoleName = "View Manager Role"
$VIRolePrivileges = @(`
# Folder
'Create Folder', 'Delete Folder',`
# Datastore
'Allocate space',`
# Virtual Machine - Configuration
'Add or remove device', 'Advanced configuration', 'Modify device settings',`
# Virtual Machine - Interaction
'Power off', 'Power on', 'Reset', 'Suspend', 'Perform wipe or shrink operations',`
# Virtual Machine - Inventory
'Create new', 'Create from existing', 'Remove',`
# Virtual Machine - Provisioning
'Customize guest', 'Deploy template', 'Read customization specifications', 'Clone template', 'Clone Virtual Machine',`
# Resource
'Assign virtual machine to resource pool',`
# Global
'Act as vCenter Server',`
# Host
'Advanced settings',`
# Profile-driven Storage
'Profile-driven storage view', 'Profile-driven storage update'
)
try {
# Get list of current Roles
$VIRoles = Get-VIRole
# Check if Role exists
foreach($VIRole in $VIRoles) {
if ($VIRole.Name -like $VIRoleName) {
# Role exists
exit
}
}
# Assume the Role does not exist
# Create the new Role
New-VIRole -Name $VIRoleName
# Add the Privileges to the Role
foreach($VIRolePrivilege in $VIRolePrivileges) {
Set-VIRole -Role $VIRoleName -AddPrivilege $VIRolePrivilege
}
} catch {
}
Copy and paste the contents above to a new PowerShell file. This script will check if the given Role exists and exit or it will create the Role and add the Privileges. This script will not check the current assigned Privileges if the Role exists.
PowerShell error catching has been very frustrating for me. I try to do the right thing by putting code in a Try-Catch-Finally block, but continue to struggle with catching specific errors. I don’t know why the ‘thing’ I need to catch is not output with the error. I have to go through the error and ‘hunt’ for the thing to catch. Below is the basic syntax for a PowerShell Try-Catch-Finally block.
try {
# Do something
} catch [something here to catch] {
# Handle the error
} finally {
# This section will always run
}
The sample below is similar to what you would typically see after an error is caught. Unfortunately, there is nothing in the output that you can use to ‘catch’.
What you end up having to do is use
$Error[0] | Format-List * -Force
This will show a longer output of the error, and more specifically, the ‘thing’ to ‘catch’. See the highlighted text below.
Now that there is a specific Exception to catch, we can add a new catch block to our Try-Catch-Finally block.
try {
# Do something
} catch [System.Management.Automation.ParameterBindingException] {
# Handle the specific error
} finally {
# This section will always run
}
I am not quite sure why it is so hard to find the exception to use in the catch block or why it is just not part of the error output. I suppose for someone who codes in PowerShell everyday, this post will be laughable. I just wanted to make sure I recorded a post for future reference because I know for sure, I will struggle with this concept again.