Article

VMware vRealize Orchestrator (vRO) Vault Integration

The goal of this post is to walk through configuring vRO to leverage HashiCorp Vault 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 documentationto help make this very easy.

After looking at the API documentation Quick Start, 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. In the sections below, we’ll translate the curl command above into the JavaScript code we see below:

// 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 be utilized for centralized secrets management and vRO to harness that capability.