Follow vEcoShell on Twitter
We have provided an update to the VMware PowerPack, bringing the PowerPack version to 2.4.0. The following fixes are included with this new release:
This PowerPack will still require PowerCLI 4.0 Update 1 while we resolve the issues introduced with PowerCLI 4.1.
In order to update your PowerPack within vEcoShell, follow the simple proceeding steps.
You can also click the button below to manually download the latest PowerPack file:
With the release of yesterday's vSphere 4.1 from VMware, we also got to grab the next iteration of PowerCLI. As with all Vizioncore GA products (Yes, even the free ones), we have a policy of providing full support within 90 days of platform updates/release. For the first time since PowerCLI has been around, we have a critical incompatibility between vEcoShell and PowerCLI. With VMware's PowerCLI 4.1 release, the object model of the returned PowerShell objects has changed. This can be seen by executing the following command:
Get-VM | ForEach-Object {$_.GetType() | select basetype}
This command will return a list of the object types for each virtual machine in the environment. You will notice the following if you are running PowerCLI 4.0 (with or without Update 1):
VMware.VimAutomation.Client20.InventoryItemImplVMware.VimAutomation.Client20.InventoryItemImplVMware.VimAutomation.Client20.InventoryItemImpl
You will notice the following if you are running the most recent PowerCLI 4.1:
VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImplVMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImplVMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl
So what does all of this mean anyways? Well, in vEcoShell, we tie the list of available actions to specific object types. We can see with an example code snippet of one of our top-level object nodes that we simply take the default VMware typename that is returned, and extend the typename to signify that we are modifying the default VMware object by adding our own properties to it.
Get-VM | ForEach-Object { $_.PSObject.TypeNames.Insert(0,"$($_.PSObject.TypeNames[0])#VmwarePowerPackExtension") $_ ` | Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $PSStandardVMMembers -PassThru ` | Add-Member -MemberType NoteProperty -Name ManagedHost -Value $managedHost.Name -PassThru ` | Add-Member -MemberType ScriptProperty -Name OperatingSystem -Value {$this.Guest.OSFullName} -PassThru ` | Add-Member -MemberType ScriptProperty -Name IPAddress -Value {$this.Guest.IPAddress} -PassThru ` | Add-Member -MemberType ScriptProperty -Name DNSName -Value {$this.Guest.HostName} -PassThru ` | Add-Member -MemberType ScriptProperty -Name 'Memory(MB)' -Value {$this.MemoryMB} -PassThru ` | Add-Member -MemberType ScriptProperty -Name CPUCount -Value {$this.NumCpu} -PassThru ` | Add-Member -MemberType ScriptProperty -Name HDDCount -Value {$this.HardDisks.Count} -PassThru ` | Add-Member -MemberType ScriptProperty -Name NICCount -Value {$this.NetworkAdapters.Count} -PassThru ` | Add-Member -MemberType ScriptProperty -Name ParentHost -Value {$this.Host.Name} -PassThru }
When we apply the list of available actions to a particular object type within vEcoShell, we reference the object by using a full static name. We can see this static name by going into the properties of any associated action and choosing to view the "Display Configuration":
Here you can see that we've statically set the object type to the old naming convention of VMware.VimAutomation.Client20.VirtualMachineImpl#VMwarePowerPackExtended. This means that this action will not show up when the object type that is being returned is VMware.VimAutomation.ViCore.Impl.V1.Inventory.VirtualMachineImpl, such as is the case with PowerCLI 4.1.
So, what is the fix? As you can see in the screenshot above, we do have the ability to associate actions to multiple object types. What we need to do is investigate several items before doing a bulk XML update of the existing PowerPack
We're going to be formulating a plan of action this week, and will keep the community updated. I'm hoping to have a fix in place WELL before the 90-day commitment. Stay tuned to this blog or twitter @TheVESI for more information.
Once again, with the changing of seasons, it's also time to release the new vEcoShell desktop wallpaper to the masses. I actually quite appreciate the simplistic design of the summer wallpaper. I wasn't a huge fan of the Spring wallpaper, but when I get free artwork, I take what I get. In this case, the Vizioncore Creative Services team was giving an intern the opportunity to show their stuff, and asked them to create the four seasonal backgrounds in four different artistic styles for me. As you can see on the Downloads page, they styles are indeed absolutely unique. Turned out to be a great introduction for our intern, and it gave me four wallpapers to share! Now I also know which styles I like and which I don't for when we move forward into the future wallpaper releases!
Download your Summer 2010 Wallpaper from the links below!
Standard (1280x1024)Widescreen (1680x1050)iPhone
While it is very exciting to get the release of vEcoShell 1.2.6 under our belts, one of the things that is actually a little frustrating, at least to me, is that the overall customer experience doesn't actually change significantly. There are no additional scripts and only a few minor bug fixes. The whole goal of the 1.2.6 release was to make our functions more portable.
So, you may be asking: "What does more portable mean?" Simply put, I wanted to enable users to run our scripts and functionality outside of our product as well. Some have called me crazy, and I should keep people locked into my UI, but truth be told, had I limitless resources, the first thing I would change is the actual UI of the product. So, let's see what this portability is all about.
Let's start by running a simple query in vEcoShell of providing a list of all Virtual Machines:
Just so no one thinks I'm cheating, let's make the script a little more complex by adding a quick filter. For my example, I'm going to show a list of all Virtual Machines whose Operating System contains the term "Windows" by applying a filter:
Next, let's view the script that vEcoShell has executed by going into the "PowerShell Script" tab. What I want to do is run this query on a regular basis outside of vEcoShell, so I simply want to highlight and copy the entire code region for the last action that I executed:
I now want to launch the standalone script editor and paste the copied code into a new script. BEFORE I try to run the script for the first time, I do need to run the Connect-VIServer command. This can be either added to the script, or if using the vEcoShell Script Editor, you can run the quick command in the console window:
Once we have our connection established, we can execute our script in the external editor. The script will return the same list of Virtual Machines that was provided in the Admin Console.
For those looking to save this script and execute it as a standalone PS1 file, there are two things you want to validate before attempting to run this from the command line or from a Windows Scheduled Task. First, you want to make sure that the VMware PowerCLI Cmdlets are loaded. Second, you want to make sure you establish a connection to a vCenter or ESX Server within the script before executing the function. I use the following code block within all of my scripts that i wish to run standalone to handle this process for me:
#Loads VMware's PowerCLI PowerShell Cmdlets if necessary[void](Get-PSSnapin VMWare.VimAutomation.Core -ErrorVariable getVmwareSnapinErr 2> $null)if ($getVmwareSnapinErr.Count -gt 0) { Add-PSSnapin VMware.VimAutomation.Core }#Establish a connection to the VI Server based on input parametersConnect-VIServer $vimHost -User $vimUser -Password $vimPass
These lines of code must be placed AFTER the last function in a script, and BEFORE any VMware specific code is executed.
I am happy to announce that the 1.2.6 version of vEcoShell is now available on the Downloads Page. This update brings us into full compatibility with VMware PowerCLI 4.0 U1. In addition, we have decided to remove the product from beta and have provided our first stable release, which has been rigourously tested by the Vizioncore QC team. vEcoShell will remain Freeware, and continue to have a community support policy.
The major difference in 1.2.6 is in how connections to multiple vCenter or ESX Servers are managed. In previous versions, vEcoShell maintained all session management and required custom code in nearly all of it's scripts to function properly. These scripts could not run externally to vEcoShell, so the PowerShell Code tab provided limited value. With the 1.2.6 release, vEcoShell now lets PowerCLI manage all connections. This means we were able to remove all custom code from our script library. Nearly every script that is in vEcoShell today can be run externally. Simply copy a code block from the "PowerShell Code" tab after a script has completed and paste it into the script editor. After running the Connect-VIServer command in the console window, the copied funciton will run just as it does in the admin console.
What's New with 1.2.6
Since it is 2am local time for me, I will provide additional information tomorrow, including screenshots, highlighting how to copy and paste code to run vEcoShell scripts externally as scheduled tasks using Windows Task Scheduler! For now, please take a moment to check out some of the new QuickTip videos that I published earlier today.
Thanks to everyone for their continued support of vEcoShell, please enjoy the 1.2.6 release!
In preparation for tomorrow's vEcoShell 1.2.6 launch, I've taken the time to update some of our QuickTip videos. The first few have made their way online now, and show how to accomplish tedious and complex tasks in under 90 seconds by using vEcoShell. Make sure you check them out and give some feedback, preferably BEFORE I finish rendering the rest of them!
Stay tuned to this site tomorrow as we get our 1.2.6 build online and ready for your use!
Last week while I was wrapping up my 2nd of 3 trips to Europe this quarter, I was able to provide a Europe-focused webinar discussing the current and future state of vEcoShell. A few good updates came out of this opportunity to connect with our strong community:
For those interested in listing to the entire 40+ minute webinar, simply follow the link below:vEcoShell Webinar with Scott Herold
If you are interested in participating in the vEcoShell 1.2.6 pre-release, please send me a message on Twitter to @theVESI. In addition, make sure you keep your eyes peeled on the Vizioncore Community for an exciting NEW freeware product that should be launching in the next 1-1.5 weeks. There will be a new blog posting up shortly highlighting our next new Freeware product!
Updated to perform full CBT management... Enabling or Disabling in bulk with the -disable flag!
Now I realize MOST people while stranded in Amsterdam due to volcanic ash would actually go out and enjoy the sites and sounds of the city, but that didn't distract me this weekend! I managed to create a standalone script for managing CBT across a large number of VMs. Copy and paste the following code block into a new PS1 file called Set-CBT.PS1. You can then execute it from within PowerShell by using the following Examples:
EX1: Enable CBT for all VMs in a ClusterSet-CBT.ps1 -vimHost vCenter.domain.com -vimUser domain\user -vimPass Passw0rd -location Cluster ClusterName
EX2: Enable CBT for all VMs on a HostSet-CBT.ps1 -vimHost vCenter.domain.com -vimUser domain\user -vimPass Passw0rd -location Host HostName
EX3: Disable CBT for all VMs in a DatacenterSet-CBT.ps1 -vimHost vCenter.domain.com -vimUser domain\user -vimPass Passw0rd -location Datacenter DCName
#(c)2010 Scott Herold#Quest SoftwareParam ( [string] $vimHost, [string] $vimUser, [string] $vimPass, [string] $location, [string] $value, [switch] $disable = $false)#Loads VMware's PowerCLI PowerShell Cmdlets if necessary[void](Get-PSSnapin VMWare.VimAutomation.Core -ErrorVariable getVmwareSnapinErr 2> $null)if ($getVmwareSnapinErr.Count -gt 0) { Add-PSSnapin VMware.VimAutomation.Core }#Establish a connection to the VI Server based on input parametersConnect-VIServer $vimHost -User $vimUser -Password $vimPass#Specify the container type for virtual machines. This script will attempt to modify#CBT on each VM in the specified containerswitch ($location) { "Datacenter" {$vms = Get-Datacenter $value | Get-VM | Get-View} "Cluster" {$vms = Get-Cluster $value | Get-VM | Get-View} "ResourcePool" {$vms = Get-ResourcePool $value | Get-VM | Get-View} "Host" {$vms = Get-VMHost $value | Get-VM | Get-View} "vApp" {$vms = Get-VApp $value | Get-VM | Get-View} "VM" {$vms = Get-VM $value} default { "You must specify a valid infrastructure object of Datacenter, Cluster," "ResourcePool, Host, vApp, or VM in the -location parameter" }}$vms | ForEach-Object { #Exit if VM is not Virtual HW Version 7 if ($_.Config.Version -ne "vmx-07"){ "$($_.Name) - VM Hardware Version 7 is required to support CBT" return } #Exit if VM already has CBT enabled if (($_.Config.ChangeTrackingEnabled) -and ($disable -eq $false)){ "$($_.Name) - CBT is already enabled" return } #Exit if VM already has CBT disabled if (($_.Config.ChangeTrackingEnabled -eq $false) -and ($disable)) { "$($_.Name) - CBT is already disabled" return } #Change CBT and add/remove snapshot for changes to take effect on all VMDKs of VM else { $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec if ($disable) { $vmConfigSpec.changeTrackingEnabled = $false } else { $vmConfigSpec.changeTrackingEnabled = $true } $_.ReconfigVM($vmConfigSpec) sleep 3 #Using vSphere SDK and not PowerCLI calls because I am only dealing with Get-View #objects in this script for speed purposes $snap = get-view ($_.CreateSnapshot("Enabling CBT","",$false,$false)) $task = $snap.RemoveSnapshot_Task($true) if ($disable) { "$($_.Name) - CBT has been disabled" } else { "$($_.Name) - CBT has been enabled" } }}
And BTW, yes, I did managed to actually enjoy quite a bit of Amsterdam this weekend!
I took it as a personal challenge this week to leverage PowerShell, PowerCLI and the vSphere API to track the amount of data that changes in a VM over a regular interval window. It turns out VMware does make it quite simple to query what blocks in a VMDK file have changed and what the length of data is as long as you know how to structure the API call.
The following script can be run as a scheduled task in Windows on a regular interval such as every 15 or 60 minutes, or even just once a day (depending on how granular you want your data) against a single VM. This is perfect for profiling the amount of data a particular VM will need to send (uncompressed) over a network connection for backup or replication purposes.
There are a few quick things to note about this script:
You should create a standalone directory somewhere on an available hard drive of a Windows system. Create a new PS1 file using the built in script editor in Virtualization EcoShell. Copy and paste the following code block and save the file as "CBT_Tracker.ps1" in the newly created directory:
There is one optional parameter, and that is setting "-enableCBT = $true" in the batch file inside the quotes. What this will do is attempt to enable CBT on the specified VM. Once CBT is enabled, the flag is no longer needed. It also will not do any specific harm if CBT is already enabled, and will just exit the function and continue on its way.
All source files may also be downloaded from: http://vcommunity.vizioncore.com/se_vizioncore/m/semedia/374.aspx in the event you don't like copy/paste and naming new files and all that stuff.
Param ( [string] $vmName, [string] $vimHost, [string] $vimUser, [string] $vimPass, [Boolean] $enableCBT = $false)#Use the optional $enableCBT paramater at input to enable CBT on#a compatible virtual machine (HW Version 7). In order for CBT flags to take #effect, a Snapshot must be added and removed.function Add-CBTFlag { if ($vmv.Config.ChangeTrackingEnabled){ "CBT is already enabled on $vm" return } $vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec $vmConfigSpec.changeTrackingEnabled = $true $vmv.ReconfigVM($vmConfigSpec) sleep 3 $vm | New-Snapshot -Name "Enable CBT" sleep 5 $vm | Get-Snapshot -Name "Enable CBT" | Remove-Snapshot -Confirm:$false "Enabled CBT for $vm"}#Add a snapshot specific to the purposes of this scriptfunction Add-CBTSnap { $newSnap = $vm | New-Snapshot -Name "CBT Change Tracker" return $newSnap}#Remove the snapshot created for the purpose of this scriptfunction Remove-CBTSnap { param ( $vmSnap ) $vmSnap | Remove-Snapshot -Confirm:$false}#Captures the ChangeID of the snapshot, which is required for comparisson #tracking purposes. The current run of the script will always compare#current state against the previously logged ChangeID for differences.function Get-ChangeID { param ( $vmSnap ) $vmSnapv.Config.Hardware.Device | where {($_.GetType()).Name -eq "VirtualDisk"} | ForEach-Object { $vzCBT = New-Object PSObject $vzCBT.PSObject.TypeNames.Clear() $vzCBT.PSObject.TypeNames.Insert(0,"vzCBTTracker") $vzCBT ` | Add-Member -MemberType NoteProperty -Name VMName -Value $vm.Name -PassThru ` | Add-Member -MemberType NoteProperty -Name DeviceID -Value $_.Key -PassThru ` | Add-Member -MemberType NoteProperty -Name ChangeID -Value $_.Backing.Get_ChangeID() [array] $vzCBTColl += $vzCBT } return $vzCBTColl}#Writes the historic ChangeID and VMDK device information to a tracking file#This file is read on each iteration of the script to capture the previos#iterations ChangeID inforation.function Write-TrackerLog { $output = $null $cid | ForEach-Object { $output += $_.VMName + "," + $_.DeviceID + "," + $_.ChangeID + "`n" } $output | Out-File "$vm-CBTTracker.cfg"}#Reads previous state information of the VM from the Tracker.cfg file#Captures the list of changed blocks for the specified VM for each VMDK file#calculates the total size in bytes of changed block data across all VMDK#files associated with the VM.function Get-ChangedBlockSize { $chSize = 0 Get-Content "$vm-CBTTracker.cfg" | ForEach-Object { if ($_ -ne "") { $TrackerRef = $_.split(",") $changes = $vmv.QueryChangedDiskAreas($vmSnapv.MoRef,$TrackerRef[1],0,$TrackerRef[2]) $changes.ChangedArea | ForEach-Object { $chSize += $_.Length } } } $chSize = $chSize/1024/1024 return $chSize}#Writes the actual iterations change data out to a CSV filefunction Write-TrackerCSV { $longDate = Get-Date $shortDate = $longDate.toShortDateString() + " - " + $longdate.toShortTimeString() Add-Content "$vm-CBTTracker.csv" "$vm,$shortDate,$amtChanged"}#Loads VMware's PowerCLI PowerShell Cmdlets if necessary[void](Get-PSSnapin VMWare.VimAutomation.Core -ErrorVariable getVmwareSnapinErr 2> $null)if ($getVmwareSnapinErr.Count -gt 0) { Add-PSSnapin VMware.VimAutomation.Core }#Establish a connection to the VI Server based on input parametersConnect-VIServer $vimHost -User $vimUser -Password $vimPass#Load some VM variables$vm = Get-VM $vmName$vmv = $vm | Get-View#We can only run against a single VM at this point in time. This makes sure#the object being passed is a single VirtualMachineImpl object, and not a #collection.if (($vm.GetType()).Name -ne "VirtualMachineImpl"){ "Script can only run against a single VM at a time" return}#Checks to make sure VM Hardware version is 7. Terminates if not.if ($vmv.Config.Version -ne "vmx-07"){ "The Virtual Machine $vm must be VM Hardware Version 7 to support CBT" return}#If the "-enableCBT $true" flag is set as an input parameter, enables CBT #for specified VM if necessaryif ($enableCBT){ Add-CBTFlag}#If all other checks fail, this is a final failsafe to ensure CBT is enabled#on the VM before continuing the script.if ($vmv.Config.ChangeTrackingEnabled -eq $false){ "CBT is not enabled on $vm. Script cannot proceed." return}#Load up snapshot variables$vmSnap = Add-CBTSnap$vmSnapv = $vmSnap | Get-View$amtChanged = 0#Checks to see if the script has previous written out a CBTTracker.cfg file. This#would indicate file deletion, or first script run. If cfg file doesn't exist,#initializes CSV headings. If this is an iterative run, Gets the amount of#data that has changed since previous iteration. Writes to CSV file.if (Test-Path "$vm-CBTTracker.cfg") { $amtChanged = Get-ChangedBlockSize Write-TrackerCSV}else { Add-Content "$vm-CBTTracker.csv" "VMName,Time,ChangedMB"}#Capsture the current ChangeID to use against next iteration, Remove Snapshot#Write cfg data.$cid = Get-ChangeID ($vmSnap)Remove-CBTSnap ($vmSnap)Write-TrackerLog
With the script file created, use notepad or other simple text editor to create a new CMD file called "CBT_Tracker.cmd". This is what you will execute within Windows Task Scheduler. Paste the following line in the CMD file and edit with the proper parameters for your environment. Make sure you copy exactly, including the quotes.
powershell -command "& '.\CBT_Tracker.ps1' -VMName VMName -vimHost vCenter.domain.com -vimuser domain\user -vimpass Passw0rd"
You can now fire up Windows Task Scheduler and point to the CMD file. After the script runs for the first time, you will see 2 new files per VM that you set this to run against. $VMName-CBT_Tracker.cfg is used for tracking previous snapshot history for reference in the current script iteration. $VMName-CBT_Tracker.csv is the actual data file that contains the VMName, Timestamp, and Amount of data changed.
The CSV/Excel combination will let you do some creative things with the data output.
For those that haven't noticed, Windows PowerShell has really taken the world by storm over the last 12 to 15 months. Microsoft has a strong internal initiative to provide PowerShell support for all of their server applications and operating systems. The technology caught on so well that we are starting to see heavy usage of PowerShell outside of Microsoft as well. All three major hypervisor vendors are now providing PowerShell capabilities in their products via PowerShell cmdlets. In fact, we are now seeing some storage vendors like Compellent and NetApp driving their own PowerShell initiatives.
What does all this PowerShell mean? Simply put, we now have a single technology that can be used for scripting automation and management that crosses all four major layers of the virtualization stack.
The adoption of, and education surrounding PowerShell is a hot strategic goal for systems administrators in 2009 and heading into 2010. At Vizioncore we are also embracing PowerShell as a strategic internal initiative to provide maximum flexibility to our customers and integration partners. You will see us pushing forward with projects like Virtualization EcoShell, which is entirely focused on PowerShell management, as well as with our new vRanger 4.0 DPP. PowerShell will be changing the way people think about managing their infrastructures, and we are prepared to be on the front line of this movement. In order to use PowerShell scripting to resolve this issue you will need two components at a minimum:
Check back on this blog as I provide Tips and Tricks, as well as real-life examples of how PowerShell management of your Virtual Infrastructure can open up some significant possibilities to you as an administrator. For now, I've provided some useful links to help you get started.
One of the things that I’ve learned while playing with the vRanger Pro PowerPack is that our developers have built in a way to remotely connect to the vRanger Service while using PowerShell. This actually allows us to use PowerShell and Virtualization EcoShell to create a client utility that can interact with the vRanger Server. With the flexibility that Virtualization EcoShell provides, it is easy to start thinking of many invaluable use-cases for using Virtualization EcoShell alongside vRanger Pro.
To get started, you must make a few quick configuration changes on the vRanger server. First go into the X:\Program Files\Vizioncore\vRanger Pro\PowerShell directory and modify the vRanger.API.exe.config file using a text editor.
Find the following line:
<endpoint address=”http://localhost:2480/VAPIHost.svc” binding=”wsDualHttpBinding”
Replace the localhost in the file with the IP Address of the vRanger Server.
Next, you need to modify the client file, which resides in the same directory. Open the vRanger.API.PwerShell.dll.config file.
Again, replace localhost with the IP Address of the vRanger Server.
You must now restart the vRanger services on the server. I’ve personally had the best luck rebooting the vRanger server, but realize this may not be possible in all instances. vRanger is made up of 3 services that should be restarted for this change to take effect.
You may now copy the entire X:\Program Files\Vizioncore\vRanger Pro\PowerShell directory and move it to any system that has Windows PowerShell installed. Either Version 1 or Version 2 of PowerShell will suffice. Once you have the directory copied over, simply open up a standard Windows PowerShell prompt and navigate to the vRanger PowerShell directory. Type the following command to launch the vRanger Pro console for the first time:
./vRangerConsole.ps1
This command will register the proper components and allow you to add the Vizioncore vRanger Pro PowerShell library into Virtualization EcoShell. This will also allow PowerShell to interact remotely with your vRanger server to create a client-server architecture using the vRanger Pro Cmdlets!
A question that I am commonly asked when doing PowerShell/EcoShell presentations is a problem that has plagued scripts since time began. ”How do I secure my credentials so I don’t need to supply them in clear-text?” With PowerCLI, VMware enables pass-through credentials of the current logged-on user back to the VCenter server. Let’s assume two things up front:
As an initial test, which is only a proof of concept, let’s take a look at some functions that can help us bring some security into our scripts.
function Set-Password { $pw = Read-Host "Please Enter your Password" -AsSecureString $return = ConvertFrom-SecureString $pw $return}function Get-PassCred { $pass = $key | ConvertTo-SecureString $return = New-Object System.Management.Automation.PSCredential -ArgumentList "UserName",$pass $return}function Get-Connection { Connect-VIServer vcserver.domain.com -Credential $cred Get-VM | select Name}$key = Set-Password$key$cred = Get-PassCred$cred | Out-HostGet-Connection
Let’s take a look at what this does. The first function Set-Password simply prompts a user for their password and reads it directly into a SecureString Variable. Through the use of the ConvertFrom-SecureString Cmdlet, we then take our SecureString and convert it into an Encrypted Standard string. PwoerShell uses the Windows Data Protection API by default to encrypt the returned standard string.
The second function Get-PassCred takes our encrypted Standard String and converts it back into a SecureString. We then create a new PowerShell Credential object that includes a user name of “UserName” and a password made up of our SecureString value. You will need to replace the “UserName” string for this to function in your environment.
The third and final function Get-Connection uses the VMware Cmdlet Connect-VIServer to connect to our environment using our credential object. It then returns a list of VM names in our environment based on the Get-VM Cmdlet from VMware’s PowerCLI.
Again, this is all just a simple POC to show that at now time was the clear-text password ever displayed to you as the user. So how can we take these concepts and more safely deploy scripts in our environment?
One important thing to note is that your converted Standard String value is going to be different every time it is run. The Microsoft Data Protection API uses timestamps as part of its encryption algorithm, so it will likely be impossible to generate the identical key twice. The following standalone script should be your starting point in securing your scripts.
$pw = Read-Host "Please Enter your Password" -AsSecureStringConvertFrom-SecureString $pw#Optional replacement to Line 2#ConvertFrom-SecureString $pw | Out-File c:\encryptedpw.txt
The above script is identical to our Set-Password function in our proof of concept code. The one optional modification here is that we can either dump out the Standard String to host output, or we can capture it into a text file. I personally prefer dumping it out to a text file as it makes the script code more manageable and easier to understand. You will be using the Standard Screen output or the text file in every script you want to protect. It is also important to note here that the Microsoft Data Protection API ties the specific encryption detail to the user ID that generates it. It will not be possible to create the encrypted Standard String as UserX, and execute it as UserY. You will need to run this script and generate the encrypted Standard String as the user you will be scheduling or executing your scripts with.
Now that we have our Encrypted Standard String, we are all set to create some scripts that use this information. You will need to start every script with the following block of code to take advantage of our Encrypted Standard String (If you choose the Copy/Paste method of your Encrypted Standard String, it will be much longer that what is displayed..I cut mine off for display/formatting purposes.)
$secPass = "01000000d08c9ddf0115d1118c7a00c04fc297eb0100" | ConvertTo-SecureString#Optional Replacement for Line 1#$secPass = Get-Content c:\encryptedpw.txt | ConvertTo-SecureString$bStr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secPass)$pass = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bStr)$pass