Working with Web Services, SOAP, PHP and all the REST with PowerShell
In order to truly ascend to the next level, every scripter eventually needs to integrate an outside service into the organization, be it Air-Watch, ServiceNow, LogicMonitor, Azure AD or any other popular service.
Some of these services include ready made PowerShell modules which you can easily integrate into the environment, but others instead present something different, an API, or Application Programming Interface.
These sound scary and âdeveloperyâ but they really arenât so bad. And the great thing is that they all adhere to the same standard, er, or set of standards.
Fortunately, most of the services weâll find will adhere to one of these common standards: SOAP, REST, or PHP.
The goal of this post is to give you an example of how to use each of these standards to interact with the various systems you may run across.
Not only for the web
You may have noticed on the past few posts here that Iâm really getting into APIs. âWhatâs so great about APIs?â you may ask.
APIs allow you to very easily leverage work that someone else has done to quickly create your own functions and get seriously useful output from just a little bit of work. If youâre planning to Orchestrate workflows in your environment, or create runbooks for your data center too, or if you want to make your own tools, learning how to interact with SOAP, REST and WebServices will definitely be in your favor.
The difference between your average âScriptingâ guy and an Automation Engineer or Consultant is the ability to create your own tools, from scratch, using the APIs provided. Thatâs where you start to make the big bucks.
How do I know which standard to use?
Sometimes, weâll be super lucky and the developers for our desired Service will list which type of API theyâre offering. Of course, sometimes weâre not so lucky and have to look elsewhere.
Fortunately, we can use the URL for the service to help determine which PowerShell cmdlets to use! The following chart shows the relationships between URL specification and cmdlet.
URL | Service Type | Cmdlet |
Ends in .asmx or ?WSDL | SOAP | New-WebServiceProxy |
Contains API, especially api/v2 | REST | Invoke-RESTMethod |
Ends in .php | PHP/Form | Invoke-WebRequest |
REST v. Soap, whats the difference?
This is a great question that came up during our userâs group last night. Both REST and SOAP are simply methods of accessing information presented via web services. It will suffice to say that REST is now in vogue, and is generally believed to be easier to use and manage than SOAP, which tends to be a bit heavier on XML.
The best answer Iâve seen came from Dr. M. Ekelstein, who put it the following way: âA nice analogy for REST vs. SOAP is mailing a letter: with SOAP, youâre using an envelope; with REST, itâs a postcard. â
In his blog he gives an example, comparing the response you can expect from SOAP vs. the response from REST. In both examples, weâre querying for the results of a user â12345â. Note the tremendous verbosity of one reply over the other.
SOAP | REST |
<?xml version="1.0"?><soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:body pb="http://www.acme.com/phonebook"> <pb:GetUserDetails> <pb:UserID>12345</pb:UserID> </pb:GetUserDetails> </soap:Body> </soap:Envelope> | http://www.acme.com/phonebook/UserDetails/12345 |
You can imagine how much work would go into parsing out the real juicy bits from the result on the left, versus the result on the right.
Simply put, if you have the option, use REST, itâs much easier to deal with the return objects!
Working with SOAP Protocol
So, weâve determined that weâre working with a SOAP API, either because the service API catalog says so, or we used the handy URL trick to determine that the URL of this service ends in .asmx?WSDL, which is short for Web Services Description Language.
The overall flow of accessing resources from a SOAP source are to access the source using New-WebServiceProxy, storing the results in a variable. Youâll then run Get-Member to look at the methods your WebService offers, and then go from there with accessing it.
You can generally view a WSDL in your browser by, uh, browsing to it. It will be human readable XML code. For this example, weâll be using the handy Length endpoint from WebServiceX.net, which allows us to convert one unit of Length into another. When we open it in a browser, we see the following Service Description.
Fortunately for us, rather than scrolling through pages and pages of XML, PowerShell knows how to interpret this description and let us access it in a PowerShell-y way, using the New-WebServiceProxy cmdlet.
For example:
$url = "http://www.webservicex.net/length.asmx?WSDL"
$proxy = New-WebServiceProxy $url $proxy | gm -memberType Method
TypeName: .AutogeneratedTypes.WebServiceProxy
Name MemberType Definition
---- --------- ----------
ChangeLengthUnitCompleted Event
BeginChangeLengthUnit Method System.IAsyncResult
ChangeLengthUnit Method double ChangeLengthUnit
ChangeLengthUnitAsync Method void ChangeLengthUnitAsync
EndChangeLengthUnit Method double EndChangeLengthUnit
ToString Method string ToString()
So, this helpful output lets us see some interesting Methods() available, all centered around Changing Length Units. Letâs take a peek at the .ChangeLengthUnit() method.
Those definition types are super long! It basically abbreviates down to (âNumberOfUnitsâ,âStartingLengthUnitâ,âEndingLengthUnitâ)
We can give it a try with the following, to convert 15 Meters into a similar number of International Confusing Headache Increments (INCHEs, for short)
$serviceProxy.ChangeLengthUnit(15,"Meters","Inches")
 >590.551181102362
Pretty nifty!
Working with REST
REST APIs are the bomb, and totally fly AF. Theyâre written when the developers of a service truly have extensibility in mind.
For this example, weâll refer back to my Get-Weather function I released about a month ago. When I originally wrote that, I was using Invoke-WebRequest (Which is effectively just loading the web page and scraping itâs contents! Iâve since had a come to Jesus meeting and fixed my code there )
Here are the most pertinent bits of that function:
$API\_key = "$secret" $url = "https://api.forecast.io/forecast/$API\_key/$coords" #Store the results in $weather $weather = Invoke-RestMethod $url -Method Get
#Display the contents of $weather $weather
latitude : 33.9533
longitude : -84.5406
timezone : America/New_York
offset : -5
currently : @{time=1416415006; summary=Clear; icon=clear-day; nearestStormDistance=235; nearestStormBearing=321; precipIntensity=0;
precipProbability=0; temperature=38.67; apparentTemperature=36.25; dewPoint=20.8; humidity=0.48; windSpeed=3.54; windBearing=249;
visibility=10; cloudCover=0.09; pressure=1029.21; ozone=321.84}
minutely : @{summary=Clear for the hour.; icon=clear-day; data=System.Object[]}
hourly : @{summary=Partly cloudy starting this afternoon, continuing until this evening.; icon=partly-cloudy-day; data=System.Object[]}
daily : @{summary=Light rain on Saturday through Tuesday, with temperatures rising to 67âF on Monday.; icon=rain; data=System.Object[]}
flags : @{sources=System.Object[]; isd-stations=System.Object[]; darksky-stations=System.Object[]; madis-stations=System.Object[];
lamp-stations=System.Object[]; units=us}
So,now that weâve seen how easy it is to work with these object oriented services, letâs take a deeper peak under the covers with some PHP/Forms manipulation using PowerShellâs built-in FaceBook example.
Working with PHP/Web Forms Objects
Now, that weâve seen how comparatively easy these were, letâs see how weâd attack a .php/forms login.
One of the things to note about using Invoke-WebRequest is that youâll be getting cozy with the HTTP Verbs of Get, Post, Delete, and others. For this example, weâll use Get and Post.
Weâll run our test using the easiest .php that I know of, the Form Post Tester service on Hashemian.comâs blog. The usage of this service is that you can post any data youâd like to the php system, in the -Body param of your submission. You can pull the data back down later if you append a â/â and a key to your submission, which is handy for testing your HTTP Get.
Hereâs an example.
$FormtesterUrl = http://www.hashemian.com/tools/form-post-tester.php
$accessCode = "/FoxDeploy"
$URI = $FormtesterUrl + $accesscode
Invoke-WebRequest -Uri $uri -Method Post -Body "Test Message From PowerShell"
If you want to test that it worked, you can open up the full URL in a browser, and see something like this.
Now to pull the data back down from there, weâll do an use the âGetâ method instead.
Invoke-WebRequest -Uri http://www.hashemian.com/tools/form-post-tester.php/FoxDeploy -Method Get | Select -expand Content
In more complex scenarios, you could read the HTML of a page and provide values for all of the fields on a page to log in. If you check the Get-Help example, youâll find a very ambitious example that allows you to log into Facebook with PowerShell!
Where to go from here
I hope you liked this quick tour through working with various APIs. For your next steps, you might be interested in how to work with complex authentication, covered here in Using PowerShell and oAuth.
Have a specific question? Iâve written modules for dozens of APIs, from AirWatch, to ServiceNow and even Imgur and can help you get your API needs sorted.  Leave a message below, or on reddit.com/r/FoxDeploy and weâll see what we can do!