Press "Enter" to skip to content

Introduction to PowerShell REST API authentication

Joshua Stenhouse 6

Have you ever wanted to consume REST APIs in PowerShell but don’t know where to start? If so, you’ve come to the right place! Using 4 different REST APIs from VMware, Nutanix, Rubrik, and Zerto, I’m going to take you through everything needed to get you started.

Over the past few years, the number 1 challenge I’ve found is simply authenticating. Once you’re in its relatively straightforward, but if you can’t authenticate then you’ve got nothing. I will show you how to get past this in 5 simple steps.

Note: The examples provided are correct and working as of VMware vCenter 6.5, Nutanix/AOS 5.1, Rubrik 4.0 and Zerto 5.5. They should continue to work on newer versions, but if you find they don’t please let me know via the comments.

Step 1
Start by assigning variables for the REST API server name or IP address along with the credentials to authenticate:

$RESTAPIServer = "ServerDNSNameOrIPHere"

The 3 most common ways to specify credentials for authentication are:

1. Plain text (not preferred):

$RESTAPIUser = "admin"
$RESTAPIPassword = "password"

2. Prompt for credentials (good for manual testing):

$Credentials = Get-Credential -Credential $null
$RESTAPIUser = $Credentials.UserName
$Credentials.Password | ConvertFrom-SecureString
$RESTAPIPassword = $Credentials.GetNetworkCredential().password

3. Store and retrieve credentials securely (preferred for production):

# Run once to create secure credential file
GET-CREDENTIAL –Credential (Get-Credential) | EXPORT-CLIXML "C:\SecureString\SecureCredentials.xml"
# Run at the start of each script to import the credentials
$Credentials = IMPORT-CLIXML "C:\SecureString\SecureCredentials.xml"
$RESTAPIUser = $Credentials.UserName
$RESTAPIPassword = $Credentials.GetNetworkCredential().Password

Step 2
Typically the web server you are connecting to doesn’t have a trusted security certificate (on the host running the PowerShell script) so we need to change the certificate policy to prevent errors. You might also be using a REST API that requires TLS 1.2, which isn’t enabled by default in PowerShell 5 and below. If you load the URL in your web browser you can very quickly see whether the certificate is trusted or not. If it’s not trusted, you need to add the below to ensure it doesn’t break your REST API calls:

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'

If you’re using PowerShell Core 6.0 don’t use the above code. Instead, add a -SkipCertificateCheck to each of your REST API calls (and TLS1.2 is supported natively):

Invoke-RestMethod -SkipCertificateCheck
Invoke-WebRequest -SkipCertificateCheck

Step 3
We need to specify the authentication URL, build a basic authorization header and set the data type we will be working with. The only thing that changes between the vendor examples is the URL, the rest you can see stays the same:

VMware:

$BaseAuthURL = "https://" + $RESTAPIServer + "/rest/com/vmware/cis/"
$BaseURL = "https://" + $RESTAPIServer + "/rest/vcenter/"
$vCenterSessionURL = $BaseAuthURL + "session"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"

Rubrik:

$BaseURL = "https://" + $RESTAPIServer + "/api/v1/"
$RubrikSessionURL = $BaseURL + "session"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"

Zerto:

$BaseURL = "https://" + $RESTAPIServer + ":9669/v1/"
$ZertoSessionURL = $BaseURL + "session/add"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"

Nutanix:

$BaseURL = "https://" + $RESTAPIServer + "/PrismGateway/services/rest/v2.0/"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"

Step 4
To authenticate we need to use Invoke-RestMethod -Method POST with the URL and header we created. We then parse the response for a session ID/token which we put into a header for subsequent REST API calls. You’ll see that each vendor gives you a slightly different response and documentation around this is typically presumptive of this step so these examples are good to keep handy.

Most of the time Invoke-RestMethod will suffice for authentication. However, there are some vendors where only Invoke-WebRequest returns the data needed. It performs the same action, but it changes the way PowerShell parses and presents the response. You’ll see me switch between them in the examples below:

VMware:

Try 
{
$vCenterSessionResponse = Invoke-RestMethod -Uri $vCenterSessionURL -Headers $Header -Method POST -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the session ID from the response
$vCenterSessionHeader = @{'vmware-api-session-id' = $vCenterSessionResponse.value}

Rubrik:

Try 
{
$RubrikSessionResponse = Invoke-RestMethod -Uri $RubrikSessionURL -Headers $Header -Method POST -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the token from the JSON response
$RubrikSessionHeader = @{'Authorization' = "Bearer $($RubrikSessionResponse.token)"}

Zerto:

Try 
{
$ZertoSessionResponse = Invoke-WebRequest -Uri $ZertoSessionURL -Headers $Header -Method POST -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the token from the JSON response
$ZertoSession = $ZertoSessionResponse.headers.get_item("x-zerto-session")
$ZertoSessionHeader = @{"Accept"="application/json"
"x-zerto-session"="$ZertoSession"}

With Nutanix I’ve been unable to find an authentication mechanism that gives me a session ID or token to re-use on subsequent calls. Instead, just skip to the next step and pass the authentication Header to each API call. If you know a better way let me know and I’ll update my example.

If you receive any errors double check the URL and credentials are correct by logging into the web interface using the data specified in the script. If it’s still not working, run the xx variable to see what was returned to make sure you are getting a response and parsing for the correct data.

Step 5
Now we’ve authenticated let’s test the REST API with a simple GET command. If no Method is specified on Invoke-RestMethod it uses GET. The acceptable methods listed in order of commonality are:

GET, POST, DELETE, PUT, PATCH, MERGE, TRACE, HEAD

You should use the URL and Method specified by the vendor documentation on the API call you are making.

VMware:

$VMListURL = $BaseURL+"vm"
Try 
{
$VMListJSON = Invoke-RestMethod -Method Get -Uri $VMListURL -TimeoutSec 100 -Headers $vCenterSessionHeader -ContentType $Type
$VMList = $VMListJSON.value
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
$VMList | Format-Table -AutoSize

Rubrik:

$VMListURL = $BaseURL+"vmware/vm?limit=5000"
Try 
{
$VMListJSON = Invoke-RestMethod -Uri $VMListURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$VMList = $VMListJSON.data
}
Catch 
{
$_.Exception.ToString()
$Error[0] | Format-List -Force
}
$VMList | Format-Table -AutoSize

Zerto:

$VPGListUrl = $BaseURL+"vpgs"
Try 
{
$VPGList = Invoke-RestMethod -Uri $VPGListUrl -TimeoutSec 100 -Headers $ZertoSessionHeader -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$Error[0] | Format-List -Force
}
$VPGList | Format-Table -AutoSize

Nutanix:

$VMListURL = $BaseURL+"vms"
Try 
{
$VMListJSON = Invoke-RestMethod -Uri $VMListURL -TimeoutSec 100 -Headers $Header -ContentType $Type
$VMList = $VMListJSON.entities
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
$VMList | Format-Table -AutoSize

Summary
By now I’m hoping you’ve successfully authenticated with your chosen REST API and obtained some useful information to get you started. If you haven’t, or would like examples for your specific platform, then add a comment and I’ll do my best to help.

With REST APIs and PowerShell you are no longer bound by the limitations of vendor provided PowerShell modules, but where do you get more information on the REST APIs available to use? Usually the vendor has built in Swagger or some form of online/PDF documentation you can access:

VMware:
https://vCenter/apiexplorer/
Rubrik (public facing, won’t change):
https://RubrikCluster/docs/v1/playground/
Rubrik (dev, subject to change):
https://RubrikCluster/docs/internal/playground/
Zerto:
https://ZVM:9669/Help/index.html
Nutanix:
https://NutanixCluster:9440/api/nutanix/v2/api_explorer/

Full Examples
To make easy to copy and paste I’ve summarized all the examples for each platform below:

VMware:

IntroTovCenterRESTAPIsv1-Demo.zip

################################################
# Configure the variables below for the vCenter
################################################
$RESTAPIServer = "vCenterDNSNameOrIP"
# Prompting for credentials
$Credentials = Get-Credential -Credential $null
$RESTAPIUser = $Credentials.UserName
$Credentials.Password | ConvertFrom-SecureString
$RESTAPIPassword = $Credentials.GetNetworkCredential().password
################################################
# Nothing to configure below this line - Starting the main function of the script
################################################
# Adding certificate exception to prevent API errors
################################################
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
################################################
# Building vCenter API string & invoking REST API
################################################
$BaseAuthURL = "https://" + $RESTAPIServer + "/rest/com/vmware/cis/"
$BaseURL = "https://" + $RESTAPIServer + "/rest/vcenter/"
$vCenterSessionURL = $BaseAuthURL + "session"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"
# Authenticating with API
Try 
{
$vCenterSessionResponse = Invoke-RestMethod -Uri $vCenterSessionURL -Headers $Header -Method POST -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the session ID from the response
$vCenterSessionHeader = @{'vmware-api-session-id' = $vCenterSessionResponse.value}
###############################################
# Getting list of VMs
###############################################
$VMListURL = $BaseURL+"vm"
Try 
{
$VMListJSON = Invoke-RestMethod -Method Get -Uri $VMListURL -TimeoutSec 100 -Headers $vCenterSessionHeader -ContentType $Type
$VMList = $VMListJSON.value
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
$VMList | Format-Table -AutoSize
###############################################
# End of script
###############################################

Rubrik:

################################################
# Configure the variables below for the Rubrik Cluster
################################################
$RESTAPIServer = "RubrikDNSNameOrIP"
# Prompting for credentials
$Credentials = Get-Credential -Credential $null
$RESTAPIUser = $Credentials.UserName
$Credentials.Password | ConvertFrom-SecureString
$RESTAPIPassword = $Credentials.GetNetworkCredential().password
################################################
# Nothing to configure below this line - Starting the main function of the script
################################################
# Adding certificate exception to prevent API errors
################################################
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
################################################
# Building Rubrik API string & invoking REST API
################################################
$BaseURL = "https://" + $RESTAPIServer + "/api/v1/"
$RubrikSessionURL = $BaseURL + "session"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"
# Authenticating with API
Try 
{
$RubrikSessionResponse = Invoke-RestMethod -Uri $RubrikSessionURL -Headers $Header -Method POST -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the token from the JSON response
$RubrikSessionHeader = @{'Authorization' = "Bearer $($RubrikSessionResponse.token)"}
###############################################
# Getting list of VMs
###############################################
$VMListURL = $BaseURL+"vmware/vm?limit=5000"
Try 
{
$VMListJSON = Invoke-RestMethod -Uri $VMListURL -TimeoutSec 100 -Headers $RubrikSessionHeader -ContentType $TypeJSON
$VMList = $VMListJSON.data
}
Catch 
{
$_.Exception.ToString()
$Error[0] | Format-List -Force
}
$VMList | Format-Table -AutoSize
###############################################
# End of script
###############################################

Zerto:

################################################
# Configure the variables below for the ZVM
################################################
$RESTAPIServer = "ZVMDNSNameOrIP"
# Prompting for credentials
$Credentials = Get-Credential -Credential $null
$RESTAPIUser = $Credentials.UserName
$Credentials.Password | ConvertFrom-SecureString
$RESTAPIPassword = $Credentials.GetNetworkCredential().password
################################################
# Nothing to configure below this line - Starting the main function of the script
################################################
# Adding certificate exception to prevent API errors
################################################
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
################################################
# Building Zerto API string & invoking REST API
################################################
$BaseURL = "https://" + $RESTAPIServer + ":9669/v1/"
$ZertoSessionURL = $BaseURL + "session/add"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"
# Authenticating with API
Try 
{
$ZertoSessionResponse = Invoke-WebRequest -Uri $ZertoSessionURL -Headers $Header -Method POST -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
# Extracting the token from the JSON response
$ZertoSession = $ZertoSessionResponse.headers.get_item("x-zerto-session")
$ZertoSessionHeader = @{"Accept"="application/json"
"x-zerto-session"="$ZertoSession"}
###############################################
# Getting list of VPGs using JSON
###############################################
$VPGListUrl = $BaseURL+"vpgs"
Try 
{
$VPGList = Invoke-RestMethod -Uri $VPGListUrl -TimeoutSec 100 -Headers $ZertoSessionHeader -ContentType $Type
}
Catch 
{
$_.Exception.ToString()
$Error[0] | Format-List -Force
}
$VPGList | Format-Table -AutoSize
###############################################
# End of script
###############################################

Nutanix:

################################################
# Configure the variables below for the Nutanix Cluster
################################################
$RESTAPIServer = "NutanixDNSNameOrIP"
# Prompting for credentials
$Credentials = Get-Credential -Credential $null
$RESTAPIUser = $Credentials.UserName
$Credentials.Password | ConvertFrom-SecureString
$RESTAPIPassword = $Credentials.GetNetworkCredential().password
################################################
# Nothing to configure below this line - Starting the main function of the script
################################################
# Adding certificate exception to prevent API errors
################################################
add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
################################################
# Building Nutanix API Auth Header & Base URL
################################################
$BaseURL = "https://" + $RESTAPIServer + "/PrismGateway/services/rest/v2.0/"
$Header = @{"Authorization" = "Basic "+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($RESTAPIUser+":"+$RESTAPIPassword))}
$Type = "application/json"
###############################################
# Getting list of VMs
###############################################
$VMListURL = $BaseURL+"vms"
Try 
{
$VMListJSON = Invoke-RestMethod -Uri $VMListURL -TimeoutSec 100 -Headers $Header -ContentType $Type
$VMList = $VMListJSON.entities
}
Catch 
{
$_.Exception.ToString()
$error[0] | Format-List -Force
}
$VMList | Format-Table -AutoSize
###############################################
# End of script
###############################################
  1. Patrick Patrick

    This is a brilliant guide. I was able to login and use the example on Nutanix without a single error or typo.

    Thank you very much

  2. Great guide, thanks. With vROps you have to build a header and body as well to authenticate though. Just thought I’d point it out…

Leave a Reply to askareshCancel reply

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

Discover more from Virtually Sober

Subscribe now to keep reading and get access to the full archive.

Continue reading