Calling PowerShell Modules with the REST / ODATA IIS Server extension (Example 3 - WinRM)

The previous post included a link to download a modified SSH PowerShell module that would work with the Odata IIS Server extension.  The previous two posts (part1 & part2) were both about setting up the IIS server to handle Odata with PowerShell and utilising SSH via that interface.  This post provides an outline of how the Odata web-service can also be used to relay WinRM requests to machines on an accessible LAN segment.

Custom WinRM PowerShell Module

The biggest quirk I have seen from calling PowerShell modules through Odata (with Server 2012 R2) is that DNS name resolution fails when a command utilises a hostname.  For the purpose of relaying Windows Remote Management requests to a remote machine is completely dependent on being able to resolve a machine name to an IP address, this issue could potentially be a “show-stopper”.  Thankfully, there is a very simple workaround. 

I have a basic “WinRemote” PowerShell module that will invoke remote PowerShell sessions & before doing so, will use the Resolve-DnsName module (which does work) to convert a DNS name to a useable IP address.  Once a new PS session is established using an IP, full functionality of PowerShell is again available.  To enable my new WinRemote / PowerShell functionality through the Odata web-service, I need to edit the RbacConfiguration.xml file that was installed during the first part of this series.

http://www.laurierhodes.info/sites/default/files/Calling%20PowerShell%20Modules%20with%20Odata%20REST_files/image004.png

The WinRemote module I’ve been working with may be downloaded here.  As with the previous example, the new module I included in the Modules section of the RbacConfiguration.xml file.

 

Invoking the WinRemote Module

This example has a number of caveats.  You have to have Windows Remote Management enabled in your environment, which itself can be an interesting exercise for non-domain joined machines.  Assuming you can use WinRM from Odata enabled IIS server to a remote machine, the script below will return will use REST / Odata to “hop” to the remote machine and return the results of the command back across the web interface.

$server = "smaserver.domain.com"

$cred = New-Object System.Management.Automation.PSCredential `
          ("domain\laurie",(ConvertTo-SecureString "MyPassword" -AsPlainText -Force))

# Create the Request
$Headers = @{“Accept” = “application/atom+xml,application/xml”}
$body    = @{
    "OutputFormat" = "json";
    "Command" =  "Invoke-WinRemote -HostName server2012 -Command 'Get-ChildItem C:\ ' -UserName 'domain\laurie' -Password Password1234 ";
    "WaitMsec"=  7000
}

$JSON = $body | convertto-json

#Submit the Request

[xml]$invocation = Invoke-RestMethod "https://$($server):7001/MODataSvc/Microsoft.Management.Odata.svc/CommandInvocations" `
         -Method 'POST' -Headers $headers -Body $JSON -ContentType "application/json"  –Credential $cred

#A properly formed request will return a unique URI for the submitted request
$invocation.entry.id

 $LoopCount = 0

 Do
{
  $LoopCount++
  [xml]$result = Invoke-RestMethod $invocation.entry.id  -Method 'GET' -Headers $headers –Credential $cred

   "Status = $($result.entry.content.properties.Status)"
   Start-Sleep -Seconds 5

} Until ($Status –ne ‘Executing’ -or $LoopCount -eq 5)

"OutputFormat = $($result.entry.content.properties.OutputFormat)"
"Exception = $($result.entry.content.properties.Errors.element.Exception)"

 ""
# List all properties and their values
# $result.entry.content.properties

$Output = $result.entry.content.properties.Output

(ConvertFrom-Json  $Output).Fullname

There are some things to note.

The process returns an object – not a string.

The final entry in the script uses the “ConvertFrom-Json” command.  By itself, that would present the information in a far more readable representation of the objects being returned.

As I’m only really interested with the full filenames from that data, I can select that individual property from the returned data with the syntax:

(ConvertFrom-Json  $Output).Fullname

… which returns:

The example code has no error trapping prior to converting data to and from xml & Json – all of which would need to be padded-out for a production environment. 

Security

A final word should also be said in regard to security. 

Anyone with rights to query the CommandInvocations URI on the machine can retrieve the previous command list – which will display any passwords you pass in clear text.  It’s a problem that affects all orchestration tools in various ways but you have to be mindful of this danger when transferring usernames and passwords via Odata. 

At a bare minimum, IIS should be configured to use HTTPS so at least the transport is protected from snooping on the network.  The IIS server should also have firewall restrictions to limit the IP addresses that can communicate to the service.  The physical security of the server should also be considered as part of any solution using this technology.  That said, the technology is extremely powerful and creating thinking can minimise security risks effectively.

 

In this Series:

Calling PowerShell Modules with the REST / ODATA IIS Server extension
Calling PowerShell Modules with the REST / ODATA IIS Server extension (Example 2 - SSH)
Calling PowerShell Modules with the REST / ODATA IIS Server extension (Example 3 - WinRM)