VMware vRealize Orchestrator (vRO) Vault Integration

The goal of this post is to walk through configuring vRO to leverage HashiCorp Vault (https://www.vaultproject.io/) for reading secrets that will be used as part of our example workflow.

The first thing we need to do is take a look at the API documentation for Vault to determine how we can interact with Vault using REST API calls from vRO. HashiCorp provides us with excellent documentation (https://www.vaultproject.io/api/index.html) to help make this very easy.

After looking at the API documentation quick start (https://www.vaultproject.io/intro/getting-started/apis.html) we’re provided with an example curl command for reading a secret. The command below is extended to incorporate how the command would look with an actual token as well as the secret path that we’ll use in our example.

curl --header "X-Vault-Token: FJDKBNENEKEKDJ"  https://vault.grt.local:8200/v1/secret/superuser  

Below is the entire code used to read a secret from a Vault server and in the sections below we’ll translate the curl command above into the JavaScript code we see below.

// Get Vault Secret

// Create Vault Server URL
url = "https://" + vaultServerHost + ":" + vaultServerPort;

// Import SSL certificate
var ld = Config.getKeystores().getImportCAFromUrlAction();  
var model = ld.getModel();  
model.value = url;  
error = ld.execute();

//  Create REST call
var uri = url + "/v1/secret/" + vaultSecretPath;  
System.log(uri);  
var method = "GET";  
var httpRestHost = null;

//  Create a dynamic REST host:

var restHost = RESTHostManager.createHost("dynamicRequest");  
restHost.operationTimeout = 900;  
httpRestHost = RESTHostManager.createTransientHostFrom(restHost);  
httpRestHost.operationTimeout = 900;

//  Remove the endpoint from the URI:
var urlEndpointSplit = uri.split("/");  
var urlEndpoint = urlEndpointSplit[urlEndpointSplit.length - 1];  
uri = uri.split(urlEndpoint)[0];

httpRestHost.url = uri;  
httpRestHost.hostVerification = false;

//  REST client only accepts method in all UPPER CASE:
method = method.toUpperCase();

var request = httpRestHost.createRequest(method, urlEndpoint);  
request.contentType = "application/json";

System.debug("REST request to URI: " + method + " " + request.fullUrl);

// Vault Token Authentication
request.setHeader("X-VAULT-TOKEN", vaultToken);

var response = request.execute();   //  This should have a 90-second timeout  
System.debug("Response status Code: " + response.statusCode);

if ( response.contentAsString )  
{
  var output = JSON.parse(response.contentAsString);
  System.log("Vault Secret: " + output.data.value );
}

Authentication

Vault supports a number of authentication methods like username/password, TLS certificate and several others but for this example we’re going to use default token based authentication.

To support token based authentication in our REST API call from vRO we just need to include our token as part of the request header.

"X-Vault-Token: $VAULT_TOKEN"

To translate this into our vRO JavaScript we would just use the setHeader method for our API request.

// Vault Token Authentication
request.setHeader("X-VAULT-TOKEN", vaultToken);  

In our example we’re using a “vaultToken” secure string input parameter to provide flexibility.

Vault Server

Now that we’ve walked through the header used for authentication we’ll focus on the server or host portion of the URL used in the curl command.

https://vault.grt.local:8200/v1/secret/superuser

The parts we’re concerned with are the server hostname or IP address and the server port number. We’ll create two additional input parameters “vaultServerHost” and “vaultServerPort” and from those we’ll compose the full URL used for the Vault server API call.

// Create Vault Server URL
url = "https://" + vaultServerHost + ":" + vaultServerPort;  

Reading a secret

The last portion of the curl command that we need to address is the api specific portion that contains the API version, vault secret path and finally the name of the secret we want to retrieve from Vault.

https://vault.grt.local:8200/v1/secret/superuser

The “/v1/secret” is static so we’ll hardcode it and create an input parameter named “vaultSecretPath” to specify what secret we want out of vault.

var uri = url + "/v1/secret/" + vaultSecretPath;  

To test this the previously discussed input parameters need to be created, bound to a Scriptable Task that contains the code from the beginning of the post and then we can run it to see our secret from vault.

Enter in the required information for the workflow and click “Submit”

If the workflow ran successfully we should be able to see the secret printed out to the log. This is for example purposes but secrets should never be printed out in plaintext.

Extensibility

This example walked through a small portion of what’s possible with vRO and Vault integration but the benefit is immense as it enables Vault to utilized for centralized secrets management and vRO to harness that capability.

References

Vault HTTP API
https://www.vaultproject.io/api/index.html