Category Archives: PowerCLI

Make PowerShell As Cool As You. Modify Your Default Profile.

Do you feel that PowerShell just isn’t as cool as you?  Do you wish that you could make it cool like yourself?  Me too!

So how do we do this?  By modifying the default PowerShell profile.  The default profile is just a standard ps1 file that runs each time you launch a PowerShell Console.  A quick search online and you’ll find there are five different locations this profile can live -crazy huh.   There’s All Users, ISE, Personal.  The best one to modify I found is the one that lives in your WindowsPowerShell folder in your User Profile path (C:\Users\{Username}\Documents\WindowsPowerShell\).  By default the file probably doesn’t exist but you can easily create it by making a file called profile.ps1 and placing in this path.

One of the quickest ways to enhance the PowerShell prompt is to add a little ASCII art to PowerShell when the console is first loaded.   I originally got the idea from a session I went to by Chris Wahl.  Chris used a simple one line piece of ACSII art showing his venting of emotion flipping a table.  You can find a lot of this art at http://www.copypastatroll.com/one-line-ascii-art/.  The issue I found was using the extended ASCII character set was difficult to use.  Most of the time it didn’t translate well using Write-Host in PowerShell.

This gave me the idea of using a here-string to create a multi-line string.  It opens the door to creating large ACSII art images using the standard character set which makes it much more compatible on-screen.  A good starting place for this art is www.chris.com/ascii/

So how can we achieve this?  As mentioned above we create a profile.ps1 file in ‘C:\Users\{Username}\Documents\WindowsPowerShell\’.  Then paste our art between @” and “@ characters and save it to a variable.  In the below example we call it $block.

We can print it out on the screen using Write-Host which also allows us to change the foreground color using -ForegroundColor.


$block = @"

.     .       .  .   . .   .   . .    +  .
  .     .  :     .    .. :. .___---------___.
       .  .   .    .  :.:. _".^ .^ ^.  '.. :"-_. .
    .  :       .  .  .:../:            . .^  :.:\.
        .   . :: +. :.:/: .   .    .        . . .:\
 .  :    .     . _ :::/:               .  ^ .  . .:\
  .. . .   . - : :.:./.                        .  .:\
  .      .     . :..|:                    .  .  ^. .:|
    .       . : : ..||        .                . . !:|
  .     . . . ::. ::\(                           . :)/
 .   .     : . : .:.|. ######              .#######::|
  :.. .  :-  : .:  ::|.#######           ..########:|
 .  .  .  ..  .  .. :\ ########          :######## :/
  .        .+ :: : -.:\ ########       . ########.:/
    .  .+   . . . . :.:\. #######       #######..:/
      :: . . . . ::.:..:.\           .   .   ..:/
   .   .   .  .. :  -::::.\.       | |     . .:/
      .  :  .  .  .-:.":.::.\             ..:/
 .      -.   . . . .: .:::.:.\.           .:/
.   .   .  :      : ....::_:..:\   ___.  :/
   .   .  .   .:. .. .  .: :.:.:\       :/
     +   .   .   : . ::. :.:. .:.|\  .:/|
     .         +   .  .  ...:: ..|  --.:|
.      . . .   .  .  . ... :..:.."(  ..)"
 .   .       .      :  .   .: ::/  .  .::\

"@

Write-Host $block -ForegroundColor Green

We don’t stop here though.  There’s a few other things we can do.  Most of my code lives in a specific folder.  So we can modify the default folder path that PowerShell opens to by added the below code to the bottom of the profile.ps1 file.  The next time PowerShell opens its defaults to this path.

Set-Location 'C:\Folder\Code'

Let’s now fix that crappy Title Bar and change it to something more inspirational.

$host.ui.RawUI.WindowTitle = 'Know yourself and you will win all battles.'

Finally let’s fix that bland prompt and give it a little color.

function Prompt
{
    $promptString = "PS " + $(Get-Location) + ">"
    Write-Host $promptString -NoNewline -ForegroundColor Cyan
    return " "
}

Let’s see what our PowerShell Console now looks like.  Much better!  We can now show people how cool we really are.  When people see our console they will tremble in our PowerShell skillz 😛

Putting it all together, let’s see what the code looks like.

$block = @"

.     .       .  .   . .   .   . .    +  .
  .     .  :     .    .. :. .___---------___.
       .  .   .    .  :.:. _".^ .^ ^.  '.. :"-_. .
    .  :       .  .  .:../:            . .^  :.:\.
        .   . :: +. :.:/: .   .    .        . . .:\
 .  :    .     . _ :::/:               .  ^ .  . .:\
  .. . .   . - : :.:./.                        .  .:\
  .      .     . :..|:                    .  .  ^. .:|
    .       . : : ..||        .                . . !:|
  .     . . . ::. ::\(                           . :)/
 .   .     : . : .:.|. ######              .#######::|
  :.. .  :-  : .:  ::|.#######           ..########:|
 .  .  .  ..  .  .. :\ ########          :######## :/
  .        .+ :: : -.:\ ########       . ########.:/
    .  .+   . . . . :.:\. #######       #######..:/
      :: . . . . ::.:..:.\           .   .   ..:/
   .   .   .  .. :  -::::.\.       | |     . .:/
      .  :  .  .  .-:.":.::.\             ..:/
 .      -.   . . . .: .:::.:.\.           .:/
.   .   .  :      : ....::_:..:\   ___.  :/
   .   .  .   .:. .. .  .: :.:.:\       :/
     +   .   .   : . ::. :.:. .:.|\  .:/|
     .         +   .  .  ...:: ..|  --.:|
.      . . .   .  .  . ... :..:.."(  ..)"
 .   .       .      :  .   .: ::/  .  .::\

"@

Write-Host $block -ForegroundColor Green

Set-Location 'C:\Folder\Code'

$host.ui.RawUI.WindowTitle = 'Know yourself and you will win all battles.'

function Prompt
{
    $promptString = "PS " + $(Get-Location) + ">"
    Write-Host $promptString -NoNewline -ForegroundColor cyan
    return " "
}

Pretty simple right.  A few small additions and we’ve brought our console to life.  When all is said and done though, none of this will actually make us better scripters.  But when your spending all day at a console prompt why not bring a little of you into it?  I’d love to know what you do?

Streaming Datasets – PowerShell | PowerCLI | Power BI

A large part of my day is spent scripting in PowerShell, specifically with PowerCLI.  One of the strongest areas of PowerCLI, obviously, is being able to retrieve information.  It’s one of the key use cases, in my opinion, for using PowerCLI in a VMware environment, it’s ability to retrieve information for Capacity planning and reporting.

Recently I’ve been looking at how to consume all that information.  You can obviously export it to a CSV, push it into a database, or something that I’ve been playing around with recently, stream it into Power BI.  Now if you haven’t tried it out yet, PowerBI is an analytics service from Microsoft.  At its core it’s a data warehouse for business intelligence.  But putting all those fancy words aside, I use it to create fancy reports.

Exporting information out of a vCenter environment with PowerCLI is dead simple.  I have dozens of scheduled tasks running all the time doing this.  Where I’ve fallen down, is taking that information and trending it over time.  This is where the Streaming Datasets functionality of Power BI comes in.  Using PowerCLI I can get an Object and Value from vCenter and then Post that directly into Power BI, using their API, and have it instantly graphed in a report.  I can then share that report out to anyone I want.  Power BI lets me do this over and over, almost as fast as I can pull the information out of vCenter.

In the example below I show how to create a trend report over time that displays Total and Available Storage of a vCenter Cluster.  Rather simple, I know, but can easily be adapted to show things like number of running VMs running, reserved resources used, etc, etc.  The skies the limit really.

Before we do any scripting the first thing we do is log into Power BI.  If you don’t have an account, don’t worry, the basic version is free.  Hit the Sign Up link and make sure you select Power BI and not Power BI Desktop for Windows, we want the cloud version.

Once logged in we click on Streaming Datasets in the bottom left under the Datasets category.  This is where we create our initial dataset schema so that it can accept streaming input.  We click on ‘Add streaminig dataset’ in the top right.

Then select the source of data, which will be API and click next.

We give our New Streaming Dataset a name and define a few values.  In this example we will define a Date, Total Storage, and Available Storage value, turn on Historic Data Analysis and click Create.  Make note of your data type to the right of the value.  Date is DateTime and the other two are Numbers.

We’ve now created our schema and are provided with a Push URL address and sample code in a few different formats (we want PowerShell).  If you look carefully we are using an Invoke-RestMethod to Post to Power BI.  This sample code has just provided us the template and hardest part of our PowerShell / PowerCLI script.  Click over the code and copy / pasta it out to use in our script (Paste it at the bottom of the script as it will be the last thing that runs).

Now we actually start on the PowerShell / PowerCLI script.  To keep it as concise as possible.  I’ve skip the process I use to actually connect to the vCenter and retrieve the information out using PowerCLI in the code below.  The real goal here is just to retrieve some values and get that into Power BI.  Line 6 is basically retrieving all shared VMFS datastores in Cluster1.  The important lines to note, though, are 4, 8, and 9 where I store my key values in three variables.  One for Date, one for TotalStorage, and one for AvailableStorage.

Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server host.mydomain.local

$date = Get-Date

$datastore = Get-Cluster -Name Cluster1 | Get-Datastore | Where-Object {$_.Type -eq 'VMFS' -and $_.Extensiondata.Summary.MultipleHostAccess}

$TotalStorage = ($datastore | Measure-Object -Property CapacityMB -Sum).Sum / 1024
$AvailableStorage = ($datastore | Measure-Object -Property FreeSpaceMB -Sum).Sum / 1024 

The additional lines below from 11 onward is the important code.  This is our pasted sample code from Power BI that we will slightly modify to push our values up to Power BI.  Don’t copy mine, as your URL and key will be different.  On lines 13, 14, and 15 we will remove the example values and replace it with our three variables, $Date, $TotalStorage, and $AvailableStorage.

Import-Module VMware.VimAutomation.Core
Connect-VIServer -Server 10.1.1.201 -user "mydomain\username"

$date = Get-Date

$datastore = Get-Cluster -Name Cluster1 | Get-Datastore | Where-Object {$_.Type -eq 'VMFS' -and $_.Extensiondata.Summary.MultipleHostAccess}

$TotalStorage = ($datastore | Measure-Object -Property CapacityMB -Sum).Sum / 1024
$AvailableStorage = ($datastore | Measure-Object -Property FreeSpaceMB -Sum).Sum / 1024 

$endpoint = "https://api.powerbi.com/beta/83fe1fa2-fa52-4376-b7f0-cb645a5fcfced/datasets/d57970bc-60b3-46e6-b23b-d782431a72be/rows?key=2zEhgN9mu%2BEH%2FI2Cbk9hd2Kw4b5c84YaO6W8gzFcZbBnO6rti3N631Gjw%2FveNXSBxwR84VcWPGOSrheNwQnCbw%3D%3D"
$payload = @{
"Date" = $Date
"Total Storage" = $TotalStorage
"Available Storage" = $AvailableStorage
}
Invoke-RestMethod -Method Post -Uri "$endpoint" -Body (ConvertTo-Json @($payload))

Disconnect-VIServer * -Confirm:$false

On the last line I disconnect  from my vCenter and close any sessions.  This helps if running as a scheduled task.  Finally save the script.

And that’s it for the scripting part.  Assuming everything is correct, no connection issues, correct values being retrieved.  All we have to do is run the script and it will send a POST request using Invoke-RestMethod with our three values.  We can now run this script as many times as we want and it will continue to post the current date and time along with Total Storage and Available Storage.  At this point, if we wish, we can turn the script into a scheduled task or just continue to run manually to suit our needs.

We now go back to Power BI and report on what we have.  Back on our Streaming Datasets browser window we click the Create Report icon under actions.  Now this part is going to be very subjective to the end user who wants the report.  But the key data we want is under RealTimeData on the far right.  Select all three values and we get presented with a default view of our data.  Under Visualizations select line chart and now we start to see a more visual representation of our capacity over time.  Under the Analytics section add a trend line and see a basic view of available capacity over time.  Finally hit save and you have a self updating report from streaming data.

For the report to start to look anything like below it will take time and a few sample datasets.  In the below image I’ve mocked up some numbers over time as an example.

Once you have a working script and it’s streaming data to PowerBI it’s really up to you on how to report on it.  The above example, as simple as it is, lays the ground work to more customized and complex reporting that you might not be able to get out of traditional monitoring and reporting software.  The ability is there to even share out the report.

Streaming datasets, as you might have noticed in the UR, is still in beta.  As great as I have found it to be it does have some quirks.  For one you can’t easily modify data you have already streamed up to Power BI.  So if you send incorrect data / values up to Power BI in a streaming dataset it will remain their.  At which point you will have to consider Filters to exclude it in reports.

In summary I think Power BI is a very underrated free tool from Microsoft.  I’ve only just started to scratch the surface of what’s possible with it.  The simplicity of capturing data with PowerShell and sending it to Power BI is well worth the time and effort to try at least once.  So what are you waiting for?

PowerCLI Core

When Microsoft and Jeffrey Snover released PowerShell on Linux a few months back we knew PowerCLI running on Linux wasn’t too far away.  Well, an awesome demo from Alan Renouf running PowerCLI in a Docker container was probably a giveaway 🙂

Well since then we’ve been patiently waiting, and hearing rumors of a Fling, for the release.  Earlier this week VMware finally released that Fling.  And that haven’t disappointed.  VMware have provided a number of different methods to run PowerCLI Core --OS X, Linux, and Docker.  Skimming through the Instructions PDF on the Flings site by far the easiest method has to be the Docker image from Docker Hub (assuming you already have docker installed).

I decided to try out this docker image and was pleasantly surprised at how easy it was.  Boy, I miss the old days of Linux where I had to compile and install everything, then troubleshoot, and repeat.  Using an Ubuntu 14.04 build it’s as simple as running two commands.

First pull down the docker image from Docker Hub.

docker pull vmware/powerclicore

Then run the container!

docker run --rm -it --entrypoint=’/usr/bin/powershell’ vmware/powerclicore

And that’s really it, kind of.  There is one more command you’ll have to run to actually connect to a vCenter or ESXi host.  Without it you’ll receive an Invalid Certificate error which will prevent you from connecting.

Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false

After that you should be able to connect as normal to a vCenter.

ubuntu01-vmware-workstation-000303

As the doco states not all the modules are available yet.  Currently just the Core and VDS cmdlets.  A quick check shows we have 315 available to us.  Which, to be honest, is a huge amount.

PS /powershell> (get-command -Module powercli*).count
315

I haven’t done too much with it yet.  Though I have already noticed a few odd issues and errors.  It’s hard to say if it’s PowerCLI Core related or PowerShell.  One notable issue is when pipping a PowerCLI cmdlet multiple times on the command line it would intermittently fail.

The important thing to note here is this is a Fling, which as I’ve mentioned before, is unsupported and comes with no guarantees.  Not only that but it’s build upon an Alpha build of PowerShell 6.  Put it together and sure you’ll probably get unexpected results sometimes.

Never the less this is another get testament to VMware’s commitment to PowerCLI and PowerShell.  I’m excited to see PowerShell and PowerCLI continue to further develop and mature on Linux and open the door to a whole new slew of developers.

References

PowerCLI Core Fling
VMware PowerCLI Blog Announcement

PowerShell on Linux

The big news out of Microsoft last month making headlines is the open sourcing of PowerShell.  Along with this comes the ability to now run PowerShell not just in Windows but also Linux and Mac OS X.  For people close to the PowerShell community this wasn’t unexpected, but make no mistake this is huge news.

I’m really liking this new Microsoft.  They are really embracing this open source stuff.  On first thought it’s not obvious how Microsoft will make money with PowerShell going open source.  But Microsoft isn’t stupid, this is no doubt part of a larger master plan.  With PowerShell so tightly linked to their products they are opening the door to a whole new demographic of users.  I can see PowerShell going open source being a key to getting a new mix of Linux Developers working in Azure.  Something close to my heart is VMware have also announced plans to port over PowerCLI to work with PowerShell for Linux.  As a PowerCLI tragic myself I’ve seen first hand how frustrated Mac users have been that they can’t manage their VMware infrastructure using PowerShell / PowerCLI directly from a Mac.

Microsoft have made it clear this is very early stages of an Alpha release on GitHub.  They are looking for community help to further develop and refine using PowerShell on Linux.  There’s a large number of bug fixes, growing by the day, that they need to work through before we get anywhere close to a production release.

I decided to try it out myself and i’m impressed, the future looks awesome.  Apart from Windows currently the open source version is limited to Ubuntu 14.04 /16.04, CentOS 7, and Mac OS X 10.11.

I had an Ubuntu 14.04 Linux VM that I used testing.  The first thing is to download the appropriate package over at GitHub. https://github.com/PowerShell/PowerShell

Once downloaded and depending on what OS you’re running you may need to install a few additional libraries first.  In my case it was libnuwind8 and libicu52 using apt-get. After which i was able to install the PowerShell Debian package. 

mukotic@ubuntu:~/Downloads$ sudo apt-get install libunwind8 libicu52
mukotic@ubuntu:~/Downloads$ sudo dpkg -i powershell_6.0.0-alpha.9-1ubuntu1.14.04.1_amd64.deb

Believe it or not that’s all that is required.  Whatever your Shell of choice is just type ‘powershell

mukotic@ubuntu:~/Downloads$ powershell
PowerShell 
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS /home/mukotic/Downloads> 

So what can we do.  Well, it’s still early days.  The first thing i did was just check the version.  I can see we’re running the .Net Core release of PowerShell which comes with Nano Server.

PS /home/mukotic/Downloads> $psversiontable 

Name Value 
---- ----- 
PSVersion 6.0.0-alpha 
PSEdition Core 
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} 
BuildVersion 3.0.0.0 
GitCommitId v6.0.0-alpha.9 
CLRVersion 
WSManStackVersion 3.0 
PSRemotingProtocolVersion 2.3 
SerializationVersion 1.1.0.1

Looking at what’s available to us it’s still limited to a handful of modules.

PS /home/mukotic/Downloads> Get-Module -ListAvailable 


 Directory: /opt/microsoft/powershell/6.0.0-alpha.9/Modules


ModuleType Version Name ExportedCommands 
---------- ------- ---- ---------------- 
Manifest 1.0.1.0 Microsoft.PowerShell.Archive {Compress-Archive, Expand-Archive} 
Manifest 3.0.0.0 Microsoft.PowerShell.Host {Start-Transcript, Stop-Transcript} 
Manifest 3.1.0.0 Microsoft.PowerShell.Management {Add-Content, Clear-Content, Clear-ItemProperty, Join-Path...} 
Manifest 3.0.0.0 Microsoft.PowerShell.Security {Get-Credential, Get-ExecutionPolicy, Set-ExecutionPolicy, ConvertFrom-SecureString...
Manifest 3.1.0.0 Microsoft.PowerShell.Utility {Format-List, Format-Custom, Format-Table, Format-Wide...} 
Binary 1.0.0.1 PackageManagement {Find-Package, Get-Package, Get-PackageProvider, Get-PackageSource...} 
Script 3.3.9 Pester {Describe, Context, It, Should...} 
Script 1.0.0.1 PowerShellGet {Install-Module, Find-Module, Save-Module, Update-Module...} 
Script 0.0 PSDesiredStateConfiguration {StrongConnect, IsHiddenResource, Write-MetaConfigFile, Get-InnerMostErrorRecord...} 
Script 1.2 PSReadLine {Get-PSReadlineKeyHandler, Set-PSReadlineKeyHandler, Remove-PSReadlineKeyHandler, G...

So those traditional Windows cmdlets will now work against the local Linux box.  Things like Get-Process will return the local running Linux processes.

PS /home/mukotic/Downloads> Get-Process


Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName 
------- ------ ----- ----- ------ -- -- ----------- 
 0 0 0 0 0.400 1331 549 accounts-daemon 
 0 0 0 0 0.350 1111 111 acpid 
 0 0 0 0 0.000 2248 205 at-spi-bus-laun 
 0 0 0 0 0.040 2264 205 at-spi2-registr 
 0 0 0 0 0.000 147 0 ata_sff

Another thing that’s also worth checking out is Visual Studio Code.  This is another great open source project Microsoft has going.  If you’ve used PowerShell ISE in Windows, think of a stream lined version of that, just more powerful leveraging extensions.  Head over to https://code.visualstudio.com/docs/setup/linux and download the package.

Installation was also super simple.

PS /home/mukotic/Downloads> sudo dpkg -i code_1.4.0-1470329130_amd64.deb.deb

Then run by typing ‘code’

PS /home/mukotic/Downloads> code

Ubuntu 14.04 - VMware Workstation-000296

I recommend getting the PowerShell extension right off the bat.  Click the Extensions icon on the left, search for PowerShell, and click Install

Ubuntu 14.04 - VMware Workstation-000297

Now we have all the wonders of Intellisense that we are use to in the Windows PowerShell ISE.  I really see Visual Studio Code becoming a future replacement for the Windows PowerShell ISE, which while still in development, has been quite stagnated in recent years.

So there you have it.  Jeffrey Snover, a Technical Fellow, in the Microsoft Enterprise Cloud Group has a great post and video discussing PowerShell going open source that should be checked out.

https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/

The next thing I’m hanging out for is PowerCLI on Linux.  A demo is shown in a video in the above link running inside a Docker container.  Expect to soon see a VMware Fling release for us to try out.

Get-View | Show-Object

I was recent watching a PowerShell presentation where they mentioned a cool module called PowerShellCookbook and in particular discussed a cmdlet in it called Show-Object by Lee Homes.  I instantly knew how perfect and powerful it would be with VMware’s PowerCLI Get-View.

Bare with me for a minute while I lay the ground work with Get-View.  If you’ve ever used Get-View in PowerCLI you’ll know that it brings back a ridiculous wealth of information.  When you run a cmdlet like Get-VMHost it’s really only bringing back a small subset of information back on that object.  Sometimes this is fine but sometimes we need that little bit extra to reach our objective.

For example you can run Get-VMHost esxi01.ukoticland.local

Windows PowerShell ISE-000282

What you get is a default formatted table view displaying only a few key values.  A trick some of us do is then pipe this out to a list.  Get-VMHost esxi01.ukoticland.local | Format-List

Windows PowerShell ISE-000283

Heaps more information right, but it’s still not the full picture.  There’s still a lot of information on this object that we’re missing.  Take the original cmdlet we ran above and this time let’s pipe it to Get-View.  Let’s also store it in a variable called $myHost, just so we can work with it.

$myHost = Get-VMHost esxi01.ukoticland.local | Get-View

Windows PowerShell ISE-000284

Okay, on first glance it doesn’t look like much.  But all those values that start with VMware.Vim are properties that can be drill down into.  For example $myHost.Config and $myHost.Config.Capabilities

Windows PowerShell ISE-000288

So it’s pretty cool right.  We can now start retrieving a huge amount of new information that wasn’t available to use before.  But this is like finding a needle in a haystack.  I know I’ve wasted so much time typing $something dot something dot something in the hopes of finding a value I can work with.

Well finally this brings us to Show-Object.  This is an awesome cmdlet that will let you display the object retrieved with Get-View in a grid view window that you can navigate through similar to a directory in File Explorer.  Using it is as simply as piping our variable to Show-Object.

$myHost | Show-Object

Windows PowerShell ISE-000287

Now we can explore and click around at everything available to us.  As you navigate the object in the top pane for results you’ll get member data in the bottom pane.  I see this becoming a great reference tool to help find what you’re looking for.  Not only that but it will give you the syntax to retrieve the information selected in the view pane.

So how do you get Show-Object?  Well, it’s not in PowerShell by default but can easily be obtained from the PowerShell Gallery, which, if new to you, is basically a public repository for PowerShell content.  If you’re using Windows 10 you’re half way there.  If not go get yourself the Windows Management Framework (WMF) 5. This will give you the latest version of the PowerShellGet module.  Then it’s just a matter of typing Install-Module -Name PowerShellCookbook.

Once the module is installed from the PowerShell Gallery, Show-Object is now available to use.  It’s worth noting that PowerShellCookbook comes with a huge array of extra cmdlets also worth exploring.

Finally if you do try out Show-Object and like it, there’s a “jacked up” version of it over at PoshCode by Justin Rich

 

Auditing and Alerting on vCenter Permissions – Part 2

In my previous post I discussed auditing permissions in vCenter via PowerCLI.  Going through the process of identifying account and group permissions and what objects they have been set on.  In this second of a two part post, I look at creating a vCenter Alarm in PowerCLI that will trigger when a permission is Added / Removed / or Modified which will then show up in vCenter Alarms.

Part 2 -- Generating a custom alarm on a vCenter permission change

The objective here is not to catch someone out (though you could see how it could help).  The Alarm is by no means meant to be as a deterrent or even used for auditing.  Where it’s useful is as an identifier that a permission add / remove / modification as taken place.  Once triggered a person can review the new permissions and acknowledge the alarm.

Working with vCenter Alarms in PowerCLI hasn’t reached the maturity as many other Cmdlets.  So creating new alarms with PowerCLI is not as straight forward as using a Cmdlet.  To create a new alarm ww have to use the powerful Get-View Cmdlet which exposes us to all the richness of the SDK APIs of vCenter.

Creating an alarm requires a few pieces of information.  First we create the alarm object, give it a name, description, and set its state.

Next we create our Triggers or expressions.  Creating the expression is where the magic lays.  The key piece is the EventTypeID.  This is the specific vCenter event that will trigger the alarm.  I found finding this information through VMware was extremely difficult.    With a little searching though, and playing around, I found the information I was after with Get-View eventManager.

$event = get-view eventManager
$eventman.description.eventinfo | Where-Object {$_.key -like "*permission*"}

Running the above without any filters returned a huge amount of information with possible events to trigger on.  Using the Where-Object Cmdlet I was able to filter the results to anything with the word ‘permission’.  This narrowed down the results to just four.  The key three being  PermissionAddEvent,  PermissionRemoveEvent, and PermissionUpdatedEvent.  Of course if you want to see everything just remove the pipe and everything after it.

With these events and a little more research I had enough information to now create a script for an alarm.  Below I created three expressions.  One for each Permission event and set it’s status to Yellow if triggered.  The alarm is created in the root of vCenter and will propagate down to all objects.

$alarmMgr = Get-View AlarmManager

# Create AlarmSpec object
$alarm = New-Object VMware.Vim.AlarmSpec
$alarm.Name = "Permission Modification"
$alarm.Description = "Track permission changes"
$alarm.Enabled = $TRUE

# Event expression 1 - Permission Added
$expression1 = New-Object VMware.Vim.EventAlarmExpression
$expression1.EventType = "EventEx"
$expression1.EventTypeId = "vim.event.PermissionAddedEvent"
$expression1.ObjectType = "VirtualMachine"
$expression1.status = "Yellow"

# Event expression 2 - Permission Removed
$expression2 = New-Object VMware.Vim.EventAlarmExpression
$expression2.EventType = "EventEx"
$expression2.EventTypeId = "vim.event.PermissionRemovedEvent"
$expression2.ObjectType = "VirtualMachine"
$expression2.status = "Yellow"

# Event expression 3 - Permission Modified
$expression3 = New-Object VMware.Vim.EventAlarmExpression
$expression3.EventType = "EventEx"
$expression3.EventTypeId = "vim.event.PermissionUpdatedEvent"
$expression3.ObjectType = "VirtualMachine"
$expression3.status = "Yellow"

# Add event expressions to alarm
$alarm.expression = New-Object VMware.Vim.OrAlarmExpression
$alarm.expression.expression += $expression1
$alarm.expression.expression += $expression2
$alarm.expression.expression += $expression3

# Create alarm in vCenter root
$alarmMgr.CreateAlarm("Folder-group-d1",$alarm)

# Add action to email alarm
#Get-AlarmDefinition $alarm.Name | New-AlarmAction -Email -Subject "vCenter Permission Modification Occurred" -To me@mydomain.local
#Get-AlarmDefinition $alarm.Name | Get-AlarmAction | New-AlarmActionTrigger -StartStatus 'Green' -EndStatus 'Yellow'

Commented out is also the ability to email a notification out when an event occurs.  This just feels a little overkill but never the less is a notification option.

The beauty of this script is that it can also easily be modified to alarm on any trigger-able event in vCenter.  Whether you need one expression or multiple expressions it’s easily modifiable.

Virten.net has a good article on how to create custom alarms and find events that I used for a reference.  If you don’t want to search for your own events to alarm on.  Virten maintains a database of all events that can be alarmed on.  I’m not sure how current it is but it’s a good starting point.

References

How to create custom vCenter Alarms from Events | Virten.net

Vmware Data Object -- EventAlarmExpression

Auditing and Alerting on vCenter Permissions – Part 1

In this two part post I discuss and cover how to audit vCenter permission using PowerCLI.  How to enumerate basic permissions and then expand it out and send it to a CSV file for further auditing.  In Part 2, I’ll discuss how to create custom alerts using PowerCLI to trigger an event on a vCenter permission modification.

Part 1 -- Auditing vCenter Permissions

Reviewing and auditing vCenter permissions has always been awkward at the best of times.  Unless you’re on top of permissions from day one, over time you can be left with a mess of vCenter permissions.  If you’re not explicitly looking for it you won’t know it either.  This is certainly what I found recently in one of my vCenter environments.

There are a few different ways to view permissions in the C# and Web Client.  You can click on an object and view the Permissions tab or you can go to Roles.  The Roles section is certainly much more useful but still far from ideal.  You have to click on each Role and there is no way to export that information.  Using PowerCLI on the other hand you can consolidate the above two methods into one view and have it exportable.  The quickest and easier way to get started is with Get-VIPermission once connected to a vCenter in PowerCLI.

Get-VIPermission | Format-Table -AutoSize

Get-VIPermission in its default form gives you a quick overview of all Principals / Users defined with explicit permissions along with their Role, whether it’s a group, and if it’s set to propagate down the tree .  Ideally you’ll only have a few groups listed here and nothing else.  Unlike myself, where I had a large amount of individual users explicitly listed on many different objects.

When using Format-Table we loss a little information on the screen. Namely, we can’t see on what objects these permissions are set on.  So we can work with the Get-VIPermission cmdlet to expand it out a little further.

 Get-VIPermission | sort | Format-Table Entity, EntityID, Role, Principal -AutoSize

The two extra values we are looking for here are Entity and EntityID.  In most cases Entity will aid in identifying the vCenter object that has the explicit permissions set on it so you can review.  The Entity could be a Virtual Machine, a Cluster, or a Datastore.  In some cases, though, you will find the Entity is blank.

Again, in my case I had a lot of permissions with a blank Entity.  Using EntityID I could see that the objects appeared to be networking related.  So in this case we need to get a little more creative with the querying of the SDK APIs using Get-View.

Get-VIPermission | sort | ft @{N=”ObjectName”;E={(get-view -Id $_.EntityID).name}}, Entity, EntityID, Role, Principal -AutoSize

This now gets us 95% of the way there.  We use Get-View using the EntityID as the Get-View ID to find the actual name of the vCenter object for that missing Entity value.  In the case of the networking objects we will now get the exact names of the networking switches.

get-vipermission01

Putting it all together.  In this last part I turn the one liner into a little script, make sure the correct snap-in is loaded, make it a little easier to read, and have it output to a CSV file that can be used to audit and review at a later stage.

# Import Snap-in
if ((Get-PSSnapin | where {$_.Name -ilike "Vmware*Core"}).Name -ine "VMware.VimAutomation.Core")

{
Write-Host "Loading PS Snap-in: VMware VimAutomation Core"
Add-PSSnapin VMware.VimAutomation.Core -ErrorAction SilentlyContinue
}

$Date = (get-date).tostring("yyyyMMddHHmm")
$result = Get-VIPermission | sort-object -Property Principal | Select @{N="ObjectName";E={(get-view -Id $_.EntityID).name}}, EntityID, Role, IsGroup, Principal

$result | Export-CSV -Path "$pwd\vCenter_PermissionAudit-$date.csv" -NoTypeInformation -UseCulture

In the above script the results are outputted to a CSV file appended with the date.  The benefit of doing this is you can schedule it to run and now have a history of the state of permissions over time.  Simple as it is, I think it’s really handy.

In the next post I will look at creating a basic Alarm in vCenter that will trigger when a permission is modified on an object.

Onyx For the Web Client now supports vSphere 6.0 U1

It’s been a while since I’ve used the Onyx VMware Fling.  The last time I used it was way back in 2013 running the Project Onyx version that sat as a proxy between the C# vSphere Client and vCenter.  It was a great little Fling back then.  I had a good laugh when I looked at one of my old blog posts about Project Onyx and how I felt its lifespan was limited due to the C# client being phased out for the Web Client.  Two years later and the C# vSphere Client is still going strong.  Com’on VMware, do it already 😛

Well, Onyx is now back in an all new way and it now supports the vSphere Web Client.  In fact it was released back in July 2015 but has just undergone another update for vSphere 6.0 U1.  If you’re not sure what Onyx is.  It’s a tool that allows you to record your vSphere Client actions and display them back as PowerCLI API method calls.  I found Onyx useful in years past when the PowerCLI cmdlets weren’t as mature as they are today.  Thought, today there’s still a lot of things you can’t do with the standard PowerCLI cmdlets and recently I’ve been finding I’ve been delving into the API methods more and more.  So it’s great to see support for the Web Client in Onyx now.

There are two versions of Onyx For the Web Client.  The 6.0 release and the 6.0 U1 release.  It’s important that you use the version matching your vSphere.  I learnt the hard way recently how dangerous VMware Flings can be.  I installed the 6.0 release onto vSphere 6.0 U1 and broke my vCenter good and proper.  With the latest release of Onyx only a few weeks back it now once again supports the latest vSphere Web Client.

Installation is quite simple.  In my case I’m installing to the vCenter Server Appliance (VCSA).  You download the Onyx Fling from here.  Then extract its contents to a local folder.

I then console into my VCSA and enable and change my shell to BASH

shell.set --enabled True
shell
chsh -s /bin/bash

I can now use SCP to copy the files from my local computer to the VCSA using WinSCP.  It’s just a matter of dragging the onyx-setup-60u1 folder from my computer the to the /root directory on the VCSA.

onyx_winscp-000248

Now back on the VCSA I run

cd /root/onyx-setup-60u1
chmod +x ./install.sh
./install.sh

When the install script completes it will restart your vCenter web services.  It will take a few minutes to fully restart so don’t panic if you start receiving errors when trying to browse to the Web Client.  Once the services completely restart make sure you have closed you web browser tab and reopen it to the Web Client.

It’s also ideal to change the shell back to the Appliance Shell

chsh -s /bin/appliancesh

onyx-000249

Using Onyx is super simple.  It can be found under the Inventories in the Web Client.  Also pinned to the top right corner you have to two buttons.  A Red Record icon and a PowerCLI button.  Pressing the Red Record button starts recording your web session interactions.

onyx-000251

When you’ve completed with you actions we click the same record button which has turned to a Stop button.  Pressing the PowerCLI button now shows us the PowerCLI API calls that took place to perform our actions.  All cleanly laid out with syntax highlighting.  There’s also the ability to save the output as a PowerCLI script.

That’s it really.  There’s not a great deal to this Fling.  If you don’t do much PowerCLI you might not find this Fling overly special.  If on the other hand you are using PowerCLI on a regular basis I’m sure you’ll find it interesting.

Word of warning; Onyx For the Web Client is a VMware Fling and as such does not come with official VMware support.  Onyx is best suited to a Dev and Test environment and is not really recommended for Production environments.

References:
Onyx For The Web Client

PowerCLI A Syslog Server To All ESXi Hosts In vCenter

I was recently tasked with configuring all ESXi hosts within a number of vCenter environments to use a Syslog Server.  Each of these environments contained numerous clusters and ESXi hosts.  Too many to manually want to configure a Syslog Server by hand.  Using our lab environment I played around with a few different ways of quickly pushing out some Syslog settings via PowerCLI.

I came across two different PowerCLI cmdlets that would do the job.  The  first was Set-AdvancedSetting and the second was Set-VMHostAdvancedConfiguration.  The latter being a deprecated cmdlet.  Both cmlets do the job equally well.  Ideally you would want to be using the newer Set-AdvancedSetting cmdlet rather than the deprecate one.

Where I didn’t like the newer Set-AdvancedSetting was that it would ask for confirmation before making a change.   I didn’t fully realise how annoying this would be till after I had wrote my script.   Once a connection to a vCenter is made in PowerCLI the script I created prompts for a Syslog Server then gets all ESXi hosts in the vCenter, applies the Syslog Server value, reloads syslog, and finally opens the syslog ports.  All simple and basic except that you will be prompted to apply the syslog value to each host.  Fine if you’re very cautious or if you want to omit specific hosts.

Perform operation?
Modifying advanced setting ‘Syslog.global.logHost’.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is “Y”):y

I then decided to test out Set-VMHostAdvancedConfiguration and found I preferred this cmdlet over Set-AdvancedSetting.  Each time it set a syslog value on a host it would flash up a friendly yellow little warning and go ahead with the change.  Much more convenient for large changes.  At some point in a future PowerCLI version I assume this cmdlet won’t work but until then it works a treat.

WARNING: Set-VMHostAdvancedConfiguration cmdlet is deprecated. Use
Set-AdvancedSetting cmdlet instead.

The below code block uses the newer Set-AdvancedSetting cmdlet.

# This script will set a Syslog Server all all ESXi hosts within a vCenter once connected.
# Uses the newer Get / Set-AdvancedSetting cmdlet.
# This cmdlet will require confirmation for each host being modified.
# Created by Mark Ukotic
# 04/04/2015

Write-Host "This script will change the Syslog Server on all hosts within a vCenter, restart Syslog, and open any required ports."

Write-Host

$mySyslog = Read-Host "Enter new Syslog Server. e.g. udp://10.0.0.1:514"

Write-Host

foreach ($myHost in get-VMHost)
{
#Display the ESXi Host being modified
Write-Host '$myHost = ' $myHost

#Set the Syslog Server
$myHost | Get-AdvancedSetting -Name Syslog.global.logHost | Set-AdvancedSetting -Value $mySyslog

#Restart the syslog service
$esxcli = Get-EsxCli -VMHost $myHost
$esxcli.system.syslog.reload()

#Open firewall ports
Get-VMHostFirewallException -Name "syslog" -VMHost $myHost | set-VMHostFirewallException -Enabled:$true
}

This second code block uses the deprecated Set-VMHostAdvancedConfiguration, which I prefer.

# This script will set a Syslog Server all all ESXi hosts within a vCenter once connected.
# The deprecated Set-VMHostAdvancedConfiguration cmdlet is used.
# Seems to run a little more cleaner with this cmdlet and doesn't ask for confirmation
# Created by Mark Ukotic
# 04/04/2015

Write-Host "This script will change the Syslog Server on all hosts within a vCenter, restart Syslog, and open any required ports."

Write-Host

$mySyslog = Read-Host "Enter new Syslog Server. e.g. udp://10.0.0.1:514"

Write-Host

foreach ($myHost in get-VMHost)
{
#Display the ESXi Host being modified
Write-Host '$myHost = ' $myHost

#Set the Syslog Server
Set-VMHostAdvancedConfiguration -Name Syslog.global.logHost -Value $mySyslog -VMHost $myHost

#Restart the syslog service
$esxcli = Get-EsxCli -VMHost $myHost
$esxcli.system.syslog.reload()

#Open firewall ports
Get-VMHostFirewallException -Name "syslog" -VMHost $myHost | set-VMHostFirewallException -Enabled:$true
}

Modifying Services via PowerCLI

If your vSphere environment is anything like the ones I manage over time you can be left with various ESXi hosts with Services left Running when they should be Stopped. It’s so common to turn on SSH or the ESXi Shell to troubleshoot an issue and then forget to Stop the service when you’re done.

If you’re managing 10s, if not, 100s of ESXi hosts you don’t want to be clicking on each host and checking the Security Profile setting.

This can be checked really easily and modified via PowerCLI. Below I slowly build a basic script that will check and modify a service of all hosts connected to a vCenter.

Open PowerCLI and make a connection to vCenter.

Connect-VIServer myvcenter.domain.local

Once connected we can run the following cmdlet to list all hosts in vCenter.

Get-VMHost

Next we can narrow it down by selecting an individual host then displaying all Services on that host to help identify the Service we want to modify.

Get-VMHost –Name esxi01.domain.local | Get-VMHostService

powercli_service01

This will display all services on the host, their policy state, and whether they are running.

Now we can take it one step further and enumerate all hosts looking for a specific service using its service name from the Key column above. In this case I want to list the settings for the ESXi Shell, which is defined by the Key value “TSM”

Get-VMHost | Get-VMHostService | Where {$_.Key –eq “TSM”}

powercli_service02

Next I want to now change the policy from On to Off for all hosts which we would do as follows.

Get-VMHost | Get-VMHostService | Where {$_.Key –eq “TSM-SSH”} | Set-VMHostService –Policy “On”

Finally, I want to also change the ESXi Shell on all hosts from Running to Stopped.

Get-VMHost | Get-VMHostService | Where {$_.Key –eq “TSM-SSH”} | Stop-VMHostService

powercli_service03

This will display a prompt asking you to acknowledge the operation on each or all hosts.

The scripts above are very crude but get the job done very quickly. They can obviously be narrowed down and enumerated much better. For example Get-Cluster can be used in front of Get-VMHost to target a specific cluster. Also the host’s name can be enumerated to better see which hosts you’re modifying on an individual basis. Call that your study lesson 😉