Thursday, August 19, 2010

Managing Windows with Ruby (Part 1) or...

How I learned to stop worrying and manage Windows from Linux




Intro to Windows Remote Management

I have long been a UNIX guy and have always struggled living in a mixed OS environment. Traditionally Windows based systems have made it very hard to do things remotely from systems other than other Windows boxes. This is where Microsoft's implementation of the WS-Management Protocol comes into play. The newer versions of the OS (2003 R2, Vista, 2008, and Win7) all allow you to turn on Windows Remote Management (WinRm). This is a major step forward for heterogenious envirnments because WinRM communicates over HTTP and SOAP. For more information as well as instructions on how to configure WinRM, please visit Microsoft's WinRM site. If you would like to follow along and read the WinRM docs later you can simply open up an Admin Powershell and issue the following:

winrm quickconfig
This will create an HTTP listener on port 5985 by default. I still recommend that you read the docs for more information.

Once WinRM is configured and listening the hard part is really over. Now all we need to do is pass SOAP packets back and forth in order to tell the remote Windows box what we want it to do. I have created a Ruby library called 'winrm' that aids in the building and parsing of the SOAP packets so all you have to do is call your Powershell or run your WQL and go.


WinRM for Ruby Set-up

Before diving into the examples WinRM for Ruby needs a little set-up. First and foremost the gem needs to be installed. It is up on Rubygems.org so you can just do a:

gem install -r winrm
Every program that uses WinRM will have to set-up the following:
WinRM::WinRM.endpoint = 'http://mywinhost:5985/wsman'
WinRM::WinRM.set_auth('user','pass')
winrm = WinRM::WinRM.instance
The 'winrm' instance created on the last line will be used in the following examples.

Running Powershell scripts

Powershell has a nice little option called '-encodedCommand' that lets you run a Base64 encoded script. Because of this it is relatively simple to write Powershell scripts locally and run them remotely with WinRM. To do this with the Ruby library you can simply issue

winrm.powershell(script_file)
This will return an array in the form [stdout, stderr].

Just to clarify, these scripts are local to the machine running the WinRM for Ruby library. That means you can store them on your Linux desktop or wherever you store your scripts and run them from there.


Running WMI Queries (WQL)

WMI is invaluable when enumerating system information from a Windows system. One way at getting values out of WMI is via WMI Query Language (WQL). WQL is SQL-like in syntax and very easy to use. The WinRM Ruby library implements this feature with the WinRM::WinRM#wql method. You can issue WQL queries like this:

winrm.wql 'select * from Win32_Service'
This method will return an Array of Hashes. Each Hash will contain the name/value pairs retrieved from WMI. For instance, if your WQL was
'select Name,Status from Win32_Service'
your return would look something like this:
[
  {'Name' => 'Appinfo', 'Status' => 'OK'},
  {'Name' => 'Browser','Status' => 'OK},
...
]


Give it a try...

That's a quick overview of how to use WinRM. It's a very new library so enhancements will be coming and I hope to have a Part 2 to this post that discusses the actual SOAP protocol that WinRM uses. In the meantime, give it a try and let me know how you're using it in the comments. You can also clone the source on github or open an issue on Github if you run into any issues.


Github: http://github.com/zenchild/WinRM

Cheers!

Monday, August 2, 2010

Viewpoint for Exchange Web Services - Next Generation BETA

I would like to announce the next generation, BETA release of Viewpoint, my Exchange Web Services client library for Ruby. This release has some major changes from the previous one which I'll list below. It was also developed in Ruby 1.9.x and the RSPEC tests have also completed in Ruby 1.8.7. There is much work that needs to be done adding features to the Model, but the SOAP guts have been hashed out fairly well in my mind and adding features from here on out should be fairly incremental. So without further ado, here are some of the major changes found in this BETA release.

Check out the latest code from the Viewpoint Github repository
...or install the gem version 0.1.0 "gem install viewpoint"


New SOAP backend

Viewpoint now uses Handsoap as its back-end instead of soap4r. While soap4r does some very nice things for you automatically, it ends up making your code base fairly large and it complicates any customizations that you might want to make. One example is adding custom headers. Soap4r required you to create a subclass to use as a sort of hook. I can do the same thing in Handsoap with a one-liner in the services #on_create_document method.


Models are completely rewritten

The models are completely new and not backward compatible with the old version of Viewpoint. Some of the methods still exist, but don't count on them. I've tried to make this version much more extensible than the last.

Configuration loader removed

After much thought I determined it really wasn't the place of a client library to provide a configuration loader for credentials. To that end I removed the need for a .viewpointrc file. If this is something you liked it would be relatively easy to write it into your application. Now authentication configuration information is set via class methods:
Viewpoint::EWS::EWS.endpoint = 'https://mysite.com/ews/exchange.asmx'
Viewpoint::EWS::EWS.set_auth('myuser','mypass')

Delegate access is supported

One thing that was often asked for, but missing from the previous version was delegate access to mailboxes and calendars. This is now supported via the 'act_as' parameter to the GenericFolder::get_folder method. For example:

ofolder = Folder.get_folder(:inbox,'otheruser@test.com')

If your user has delegate access to the Inbox for otheruser@test.com this operation will retrieve their inbox and allow you to manipulate it as you would with your own Inbox. There is also some support for manipulation of delegate access itself via the methods MailboxUser#add_delegate!, MailboxUser#update_delegate!, and MailboxUser#get_delegate_info.

Some Exchange 2010 Stubs


Some of the new features of Exchange 2010 are being stubbed in. I do not have access to an Exchange 2010 server to test them on so I cannot verify if they work or not.

Misc other changes

Since it's a complete rewrite there are tons of other changes that you'll notice. I've tried to keep the code comments coming so stay tuned to the API docs for library information. I'll also be posting more examples to my blog.

So at a glance there you have it. If there are any features you would like to see added or comments please add it to the bottom of this post or add an issue on the Github page. Also, if you're interested in sponsoring an Exchange 2010 account for me please let me know. I would love to try out some of the new advanced query stuff that 2010 has to offer.



Cheers!

GITHUB: http://bit.ly/viewpoint_ews
RubyGems: http://rubygems.org/gems/viewpoint
RDOC: http://rdoc.info/projects/zenchild/Viewpoint