Skip to main content

Developing PowerShell modules for REST APIs – Part1


AzureFunction

Over the years I have developed different PowerShell modules for different web APIs. I thought it would be a good idea to write a 2 series post about how you could go about to do this. This will be a 2 part blog series where we will run through the entire process of building a module for a REST API. I will try my best to keep this as simple as possible and leave more advanced stuff for a follow up post if the interest is there.

What you need

Depending on your experience with source control and PowerShell in general, you might want to use GIT or some other software repro for the code. In addition we are going to create a test REST API using the splendid UniversalDashboard PowerShell module created by Adam Driscoll. It is available on the PowershellGallery. Other prerequisites are built-in to Powershell. I will assume that you will be following along using at least PowerShell version 5 or greater.

What is HTTP metods for REST API.

The primary or most common HTTP verbs used are POST, GET, PUT, PATCH and DELETE.

  • POST - Create something
  • GET - Read or get something
  • PUT - Update or replace something
  • PATCH - Update or modify something
  • DELETE - Delete something

To keep it as simple as possible, I will focus on using POST and GET in this guide.

Authorization

APIs usually have some sort of requirement of authentication using a key. The UniversalDashboard module does not yet support authorization for REST endpoint, however we are going to fake it. My pseudo authentication method is not something you should ever use in production.

The REST API

We will create an API that enables you to list the files in a folder on your drive, sorry was the best I could come up with. The API will also let you create files with content. I know this is kind of not really exciting, however the overall goal is to keep it simple and everybody understands files.

REST Endpoints

First if you don’t have the UnversalDashboard module installed, fire up PowerShell and download the module from the Gallery:

    Install-Module -Name UniversalDashboardForce

Now we are going to create our first GET endpoint.

We create a New-UDEndpoint with the partial url of "/file/" and we will support the GET method. The endpoint it self is just a scriptblock that is executed in a separate runspace on your machine. Currently an GET Endpoint does not support parameters (Authorization) in the scriptblock like a POST endpoint does, however I included it anyway. You notice we have to extract the Authorization value from the request header from the runspace. The endpoint assumes that you have a folder ($path) on you computer with path "c:\temp\api". If the folder does not exists, you will have to create it. If the request contains the supersecret key "foo:bar" the request will get all the files in c:\temp\api and write them to the pipeline as JSON-object. If you do not understand the authorization key concept, do not worry, we will create an helper function, actually two helper functions, that will help you create the key.

Next up is our POST endpoint which is quite similar.

The POST method supports scriptblock parameters, and we need Authorization, FileName and Content parameters to be able to create files. As you may notice, we have the same decoding of the Authorization key.

Helper functions

To aid us in working with the API, we need 2 helper functions to be able to create an Authorization key. Normally the key is added as an header to a request or in the actual body of the request. We will have to add the key to the body of the request for the POST endpoint.


The Get-AuthorizationHeader is the main function that will create the key for us. The ConvertTo-Base64 function is used by Get-AuthorizationHeader to encode the key.

First test

To make sure everything is working, we will test the GET Endpoint. Copy the helper functions and the endpoint definition to your favorite PowerShell editor. Then we will start the Endpoint and create an key that can authenticate us against the API:

First we start the Endpoints by running Start-UDRestApi. You may get a firewall warning when you run the cmdlet. You have to allow traffic to the port you have selected for this to work. I selected post 11000 as the listening port for my API, however you may choose another port on your computer. Next we create a securestring containing our password "bar". Then we create a PSCredential object and pipe that to our helper function Get-AuthorizationHeader function. To test the Endpoint, we run the Invoke-RestMethod cmdlet and use the key just created. If everything work, you should have something like this in your window:

image

Those are the 3 files I have in my c:\temp\api folder.

That is it for part 1, In part 2 we will start to create a small PowerShell module and make it even more awesome. Stay tuned!

Cheers

Tore

Comments

Popular posts from this blog

Serialize data with PowerShell

Currently I am working on a big new module. In this module, I need to persist data to disk and reprocess them at some point even if the module/PowerShell session was closed. I needed to serialize objects and save them to disk. It needed to be very efficient to be able to support a high volume of objects. Hence I decided to turn this serializer into a module called HashData. Other Serializing methods In PowerShell we have several possibilities to serialize objects. There are two cmdlets you can use which are built in: Export-CliXml ConvertTo-JSON Both are excellent options if you do not care about the size of the file. In my case I needed something lean and mean in terms of the size on disk for the serialized object. Lets do some tests to compare the different types: (Hashdata.Object.ps1) You might be curious why I do not use the Export-CliXML cmdlet and just use the [System.Management.Automation.PSSerializer]::Serialize static method. The static method will generate t...

Toying with audio in powershell

Controlling mute/unmute and the volume on you computer with powershell. Add-Type -TypeDefinition @' using System.Runtime.InteropServices; [Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IAudioEndpointVolume { // f(), g(), ... are unused COM method slots. Define these if you care int f(); int g(); int h(); int i(); int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext); int j(); int GetMasterVolumeLevelScalar(out float pfLevel); int k(); int l(); int m(); int n(); int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext); int GetMute(out bool pbMute); } [Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] interface IMMDevice { int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev); } [Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), Inte...

Creating Menus in Powershell

I have created another Powershell module. This time it is about Console Menus you can use to ease the usage for members of your oranization. It is available on GitHub and published to the PowershellGallery . It is called cliMenu. Puppies This is a Controller module. It uses Write-Host to create a Menu in the console. Some of you may recall that using Write-Host is bad practice. Controller scripts and modules are the exception to this rule. In addition with WMF5 Write-Host writes to the Information stream in Powershell, so it really does not matter anymore. Design goal I have seen to many crappy menus that is a mixture of controller script and business logic. It is in essence a wild west out there, hence my ultimate goal is to create something that makes it as easy as possible to create a menu and change the way it looks. Make it easy to build Menus and change them Make it as "declarative" as possible Menus The module supports multiple Men...