Zerto Virtual Manager API Authentication with PowerShell

When beginning to leverage the Zerto Virtual Manager (ZVM) REST API for scripting operations with PowerShell the first hurdle to overcome is authentication to the ZVM and extracting the token needed in all subsequent API requests. The only real requirement is a set of credentials that is authorized to use Zerto. We will be leveraging the PSCredential Class along with the -credential parameter to simplify the operation. When we have completed our operation, we will have a variable containing the required headers we need to supply to all ZVM REST API calls to provide authentication.

NOTE: The following example was written for PowerShell Core. While the theory is the same for Windows PowerShell, there are a few subtle differences. At the end of the article I will provide full scripts for each PowerShell platform.

The first step is to define the PSCredential object with a username and password passed as a secure string.

$Username = "User@domain.tld"
$Password = "MyPassword" | ConvertTo-SecureString -AsPlainText
$Credential = [PSCredential]::New($Username, $Password)

While I do not advise storing username and passwords in script files, it will be up to you how to get the username and password passed into your script. There are several options out there depending on your work flows. One option is to do this interactively with the Get-Credential cmdlet. Use the method that works best for you.

$Credential = Get-Credential

Next we need to define the endpoint that we will be using. We will set up several variables the build the URI that can be easily changed to be reused when connecting to other ZVMs or different endpoints. Once we have the endpoint configured, we will setup our header variable that is required for the authorization call as well as end up holding our authorization token.

$ZVM = "zvm.domain.tld"
$Port = 9669
$BaseUri = "https://{0}:{1}/v1" -f $ZVM, $Port
$AuthenticationUri = "{0}/session/Add" -f $BaseUri
$Headers = @{ Accept = "application/json" }

Now that we have all of our variables setup, we can make our actual call to the server. By using PowerShell Core we will leverage the ability within the Invoke-RestMethod cmdlet to return the return header information to a specific variable. I find this method useful to aid in troubleshooting should I encounter any errors. After we make the call to the REST API, we will grab the ‘x-zerto-session’ token out of the response headers and update the $Headers variable with this information.

Note: In the parameters below, the parameter SkipCertificateCheck is set to True. This is due to using the default self-signed certificate in my lab environment. If you desire to have the certificate validated, you can remove this item or set to False. For Windows PowerShell, skipping the certificate check is not a cmdlet parameter. I have included an example of how to get around this in my gist posted at the bottom of the article.

These examples use PowerShell Splatting. Please review if you are unfamiliar.

$RequestParams = @{
    Uri                     = $AuthUri
    Headers                 = $Headers
    Method                  = "POST"
    Credential              = $Credential
    TimeoutSec              = 100
    ContentType             = "application/json"
    ResponseHeadersVariable = "responseHeaders"
    SkipCertificateCheck    = $True
}

Invoke-RestMethod @RequestParams
$Headers['x-zerto-session'] = $responseHeaders['x-zerto-session'][0]

The construction of our $Headers variable is now complete. This variable now contains the required session token and will be used to authenticate all API calls going forward by specifying it as part of the Invoke-RestMethod -Headers parameter. We can conduct a simple test to ensure that we can now make calls using our headers with the following snippet. This will be accomplished by updating our $RequestParams hashtable information removing the unneeded ‘Credential’ information and updating the specified URI.

$LocalsiteUri = "{0}/localsite" -f $BaseUri
$RequestParams.Remove('Credential')
$RequestParams['Uri'] = $LocalsiteUri
$RequestParams['Method'] = "GET"
Invoke-RestMethod @RequestParams

Once you send that last Invoke-RestMethod @RequestParams command your output should look something like this:

ZVM Local site API Endpoint Output

At this point, we have authenticated against the ZVM and obtained the required ‘x-zerto-session’ token for our $Headers variable as described in the Zerto Documentation. From this point, we now have the ability to leverage any ZVM API Endpoint. You should review the documentation to ensure you are constructing valid queries against each respective endpoint along with the method the server expects you to leverage. Happy Scripting!


Complete PowerShell Core Script:

#Requires -PSEdition Core
####################################################################################
# Update the variables below to conform to your environment
####################################################################################
$ZVM = "nczvm.nc.lab"
$Port = 9669 # This is the default, only update if you changed from the default port
$Username = "wcarroll@nc.lab"
$Password = "Zertodata!23"
####################################################################################
# Nothing to Change below this point.
####################################################################################
# Create a PSCredential Object to pass the credential information to the API
$Credential = [pscredential]::new($Username, ($Password | ConvertTo-SecureString -AsPlainText))
# Create a BaseUri string to be used in future calls the the API
$BaseUri = "https://{0}:{1}/v1" -f $ZVM, $Port
# Specify the Authentication endpoint being used
$AuthUri = "{0}/session/add" -f $BaseUri
# Setup our required headers and request parameters
$Headers = @{ Accept = "application/json" }
$RequestParams = @{
Uri = $AuthUri
Headers = $Headers
Method = "POST"
Credential = $Credential
TimeoutSec = 100
ContentType = "application/json"
ResponseHeadersVariable = "responseHeaders"
SkipCertificateCheck = $True
}
# Send the request
Invoke-RestMethod @RequestParams
# Update our headers variable with the required authentication token
$Headers['x-zerto-session'] = $responseHeaders['x-zerto-session'][0]
# Remove the 'credential' parameter as it is no longer needed
$RequestParams.Remove('Credential')
# Create a URI to test our authentication token setup
$LocalsiteUri = "{0}/localsite" -f $BaseUri
# Update the Request Parameters with the updated URI and New Method
$RequestParams['Uri'] = $LocalsiteUri
$RequestParams['Method'] = "GET"
# Send the updated request and get our localsite information
Invoke-RestMethod @RequestParams

Complete Windows PowerShell Script:

#Requires -PSEdition Desktop
####################################################################################
# This section is required if you are using the default self-signed certificate
# This next block of code will set the PowerShell session to trust all certificates
####################################################################################
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
####################################################################################
# Update the variables below to conform to your environment
####################################################################################
$ZVM = "ZVM FQDN or IP Address"
$Port = 9669 # This is the default, only update if you changed from the default port
$Username = "ENTER A USERNAME"
$Password = "ENTER YOUR PASSWORD"
####################################################################################
# Nothing to Change below this point.
####################################################################################
# Create a PSCredential Object to pass the credential information to the API
$Credential = [pscredential]::new($Username, ($Password | ConvertTo-SecureString -AsPlainText -Force))
# Create a BaseUri string to be used in future calls the the API
$BaseUri = "https://{0}:{1}/v1" -f $ZVM, $Port
# Specify the Authentication endpoint being used
$AuthUri = "{0}/session/add" -f $BaseUri
# Setup our required headers and request parameters
$Headers = @{ Accept = "application/json" }
$RequestParams = @{
Uri = $AuthUri
Headers = $Headers
Method = "POST"
Credential = $Credential
TimeoutSec = 100
ContentType = "application/json"
}
# Send the request and store the response into a variable
$Response = Invoke-WebRequest @RequestParams
# Update our headers variable with the required authentication token
$Headers['x-zerto-session'] = $Response.Headers['x-zerto-session']
# Remove the 'credential' parameter as it is no longer needed
$RequestParams.Remove('Credential')
# Create a URI to test our authentication token setup
$LocalsiteUri = "{0}/localsite" -f $BaseUri
# Update the Request Parameters with the updated URI and New Method
$RequestParams['Uri'] = $LocalsiteUri
$RequestParams['Method'] = "GET"
# Send the updated request and get our localsite information
Invoke-RestMethod @RequestParams

Banner Photo by Parsoa Khorsand on Unsplash

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s