Documenting with PowerShell: Passportal API Examples

UPDATE: The blog below is based on a private alpha/beta, and as such complete documentation is not yet available. Solarwinds is working on making the API available to everyone. 🙂

So recently I’ve gotten access to the alpha Solarwinds Passportal API, Passportal is a relatively young documentation platform that has the ability to store documents as plain html files but make a relational database out of it. The API is brand new so it’s a cool chance to make a small post about how people can approach the API and start using it for automatic documentation.

Currently the API is still in alpha/beta, so all of this blog can change. One thing to note is that currently the API endpoints cannot store passwords. That means that password-based documentation such as my Bitlocker blog is not yet available. 

I’ll consider making an unofficial Solarwinds Passportal PowerShell Module when the final version arrives, even if I’m not a regular PassPortal user I like having the same tools available. Anyway, let’s get started!

First, we’ll have to get our API key. You can get the API key by following these instructions:

Now that we have our key, we can get started with actual code. The passportal API uses access tokens to make sure that you are allowed to do anything on the API so our first job is generating an access token. Enter the required information for your environment.

$URL = "https://de-clover.passportalmsp.com/api"
$XAPIKey = "YOURAPIKEY"
$XAPISecret = "APISECRET1000"
#Next we will hash our secret to HMAC 256 using the secret "aUa&&XUQBJXz2x&". This is a preset hashing secret.
$secrethash = "aUa&&XUQBJXz2x&" #Do not change this.
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($XAPISecret)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($secrethash))
$XHash = [System.BitConverter]::ToString($signature).Replace('-', '').ToLower()
#After we have an encrypted method of sending the key we’re going to create the correct headers. 
$headers = @{
    'X-KEY'  = $XAPIKey
    'X-HASH' = $XHash
}
$Content = @{
    'content' = $secrethash
    'scope'   = 'docs_api'
}
#And now we can make a request to get our access key. This access key will be our actual login for the API this session.
$Tokens = Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/auth/client_token" -Method POST -Body $Content -ContentType "application/x-www-form-urlencoded" 

Now that we have an access token, we’ll remove our hashed API key from the headers, add our access token and try to get a list of all our clients.

#we'll remove our x-key and x-hash from the headers, and add the API access token instead. 
$headers.Remove('x-key')
$headers.Remove('x-hash')
$headers.Add('x-access-token', $Tokens.access_token)
$Clients = (Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents/clients?resultsPerPage=1000" -Method Get -Verbose).results

So with this list of information, we’re able to grab all documents for all client by adding this part:

foreach($Client in $Clients){
    (Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents?clientId=$($Client.id)" -Method Get -Verbose).results
}

To create a document for a specific client, we modify our script just a little bit and add the following code, in this example we’re filling in the default template supplied by Solarwinds within Passportal, for an Application called “Autodoc” – This application will be added to all clients.

$Clients = (Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents/clients?resultsPerPage=1000" -Method Get -Verbose).results
$TemplateID = (Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents/templates?resultsPerPage=1000" -Method Get -Verbose).results | Where-Object { $_.type -eq "application" }

foreach ($Client in $Clients) {
    $body = ConvertTo-Json @(@{
        templateUid      = $TemplateID.id
        clientId         = $client.id
        title            = "Autodoc CyberDrain.com API Test"
        application_name = "AutoDoc CyberDrain.com"
        version          = "1.0"
        notes            = "This was created with an API test."
    })

    Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents" -Method POST -Body $body -Verbose
}

Full script

$URL = "https://de-clover.passportalmsp.com/api"
$XAPIKey = "YOURAPIKEY"
$XAPISecret = "APISECRET1000"
#Next we will hash our secret to HMAC 256 using the secret "aUa&&XUQBJXz2x&". This is a preset hashing secret.
$secrethash = "aUa&&XUQBJXz2x&"
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($XAPISecret)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($secrethash))
$XHash = [System.BitConverter]::ToString($signature).Replace('-', '').ToLower()
#After we have an encrypted method of sending the key we’re going to create the correct headers. 
$headers = @{
    'X-KEY'  = $XAPIKey
    'X-HASH' = $XHash
}
$Content = @{
    'content' = $secrethash
    'scope'   = 'docs_api'
}
#And now we can make a request to get our access key. This access key will be our actual login for the API this session.
$Tokens = Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/auth/client_token" -Method POST -Body $Content -ContentType "application/x-www-form-urlencoded" 

#we'll remove our x-key and x-hash from the headers, and add the API access token instead. 
$headers.Remove('x-key')
$headers.Remove('x-hash')
$headers.Add('x-access-token', $Tokens.access_token)
#With the access key, we can make actual API requests. We'll try creating a document!

$TemplateID = (Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents/templates?resultsPerPage=1000" -Method Get -Verbose).results | Where-Object { $_.type -eq "application" }
$Clients = (Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents/clients?resultsPerPage=1000" -Method Get -Verbose).results

foreach ($Client in $Clients) {
    $body = ConvertTo-Json @(@{
        templateUid      = $TemplateID.id
        clientId         = $client.id
        title            = "Autodoc CyberDrain.com API Test"
        application_name = "AutoDoc CyberDrain.com"
        version          = "1.0"
        notes            = "This was created with an API test."
    })

    Invoke-RestMethod -Headers $headers -Uri "$($URL)/v2/documents" -Method POST -Body $body -Verbose
}

And that’s it! This API will be opening entire new avenues to documentation. I am loving the method of using plain HTML as a source for documents as most of my “Documenting with PowerShell” series has an HTML based solution too, it’s still going to take some time to evolve but with this tutorial it should be easy enough to add Passportal to my “Documenting with…” series.

Kelvin Tegelaar
Follow me

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.