vSphere SSL and vCO Part 3 – Generating the requests

In the previous post we got vCO ready to execute commands using OpenSSL and cURL for future workflows.
Now, lets get some code and workflow content going to do the real work.

Step 1 – Create the SPACE!

Let’s create a new workflow, with a single input parameter named inputHost of type VC:HostSystem

Setting up the workflow.
Setting up the workflow.

Once it’s created, drag and drop a Scriptable Task into the schema, and bind the inputHost parameter into it on the IN tab.
On the OUT tab, click the bind-icon icon, and click Create parameter/attribute in workflow.
Name the attribute workingFolder and set it as type string. This attribute will be used in future tasks of the flow.

Go to the Scripting tab of the Scriptable task, and let’s insert the code to create our temporary folder that will hold the necessary OpenSSL configuration file, private key, and CSR.

// create the temporary folder to hold the cert files
var outputFolder = System.getTempDirectory()+"/"+inputHost.name
var makeFolder = "mkdir "+outputFolder
System.log("Command to run: "+makeFolder)
// create folder
var myCommand = new Command(makeFolder)
myCommand.execute(true)

// if exitcode is 0, no errors were reported back, so it should be successful.
if(myCommand.result == 0) {
  System.log("Success, folder created.")
  workingFolder = outputFolder
} else if(myCommand.result == 1) {
  System.log("Folder already exists.")
  workingFolder = outputFolder
} else {
  System.error("There was some sort of issue creating the folder.")
}

By default, vCO can’t read/write/execute to anything, unless you have explicitly allowed it in the js-io-rights.conf file.
But there is a temporary space that it can write to that you can get dynamically using the function System.getTempDirectory() – which can be assigned to a variable as shown above. And since we are creating a sub folder inside of that space, we can better isolate the created files and use variables to find them correctly each time.

Step 2 – Create the OpenSSL Configuration file

Drag and drop another Scriptable Task into the schema.
On the INPUT side of the task, bind the inputHost parameter, and workingFolder attribute.
On the OUTPUT side of the task, click the bind-icon icon, and click Create parameter/attribute in workflow.
Name the attribute workingConfigFile and set it as type string. This attribute will be used in future tasks of the flow to create the key and CSR.

Now to the Scripting tab of the Scriptable task, and let’s insert the code to create our OpenSSL configuration file.

// get the Management IP address of the ESXi host.
var hostIpAddress = System.resolveHostName(inputHost.name)
// get hostname/fqdn
var hostName = inputHost.name.split(".")[0]
var hostFQDN = inputHost.name
// setup output file
workingConfigFile = workingFolder+"/"+hostFQDN+".cfg"
// write the configuration to a file.
var fw = new FileWriter(workingConfigFile)
try {
	fw.open()
	fw.writeLine("[ req ]")
	fw.writeLine("default_bits = 2048")
	fw.writeLine("default_keyfile = rui.key")
	fw.writeLine("distinguished_name = req_distinguished_name")
	fw.writeLine("encrypt_key = no")
	fw.writeLine("prompt = no")
	fw.writeLine("string_mask = nombstr")
	fw.writeLine("req_extensions = v3_req")
	fw.writeLine("")
	fw.writeLine("[ v3_req ]")
	fw.writeLine("basicConstraints = CA:FALSE")
	fw.writeLine("keyUsage = digitalSignature, keyEncipherment, dataEncipherment")
	fw.writeLine("extendedKeyUsage = serverAuth, clientAuth")
	fw.writeLine("subjectAltName = DNS: "+hostName+", DNS: "+hostIpAddress+", DNS: "+inputHost.name)
	fw.writeLine("")
	fw.writeLine("[ req_distinguished_name ]")
	fw.writeLine("countryName = US")
	fw.writeLine("stateOrProvinceName = Washington")
	fw.writeLine("localityName = Seattle")
	fw.writeLine("0.organizationName = ACME INC")
	fw.writeLine("organizationalUnitName = IT Team")
	fw.writeLine("commonName = "+inputHost.name)
	fw.close()
	System.log("Configuration file written to ["+workingConfigFile+"]")
} catch (e) {
	System.error("Error creating OpenSSL configuration file ["+workingConfigFile+"]: "+e)
}

The above is quite a block, but hopefully with the comments it should make some sense. At a high level we are simply creating a configuration file one line at a time, and writing it to the temporary folder.

With our OpenSSL configuration file created, let’s make our key pair files!

Part 3 – The Keymaster

Drag and drop another Scriptable Task into the schema.
On the INPUT side of the task, bind the workingConfigFile attribute, and workingFolder attribute. With the location of the configuration file and the working folder, that’s all that is needed for the task.

Now to the Scripting tab of the Scriptable task, and let’s insert the code to create our OpenSSL key and CSR from the values in the configuration file.

// create the command string
var makeCSR = "/usr/bin/openssl req -new -nodes -out "+workingFolder+"/rui.csr -keyout "+workingFolder+"/rui-orig.key -config "+workingConfigFile
System.log("Creating CSR and Private Key: "+makeCSR)
// execute the command string
var myCommand = new Command(makeCSR)
myCommand.execute(true)

You now have two files in the workingFolder : rui.csr and rui-orig.key.

Next task, you will convert the key to RSA format.

Part 4 – Transitioning to RSA

Drag and drop another Scriptable Task into the schema.
On the INPUT side of the task, bind the workingFolder attribute.

Now to the Scripting tab of the Scriptable task, and let’s insert the code to create our RSA key from the source key created above.

// create the command to convert the key
var makeNewKey = "/usr/bin/openssl rsa -in "+workingFolder+"/rui-orig.key -out "+workingFolder+"/rui.key"
System.log("Creating RSA Private Key: "+makeNewKey)
// execute the RSA conversion
var myCommand = new Command(makeNewKey)
myCommand.execute(true)

With the final key and CSR created, we need to get the contents of the CSR file and set it as the output parameter of this workflow.

Part 5 – Output the CSR

Drag and drop another Scriptable Task into the schema.
On the INPUT side of the task, bind the workingFolder attribute.
On the OUTPUT side of the task, click bind-icon and click Create parameter/attribute in workflow.
Name the attribute outputCSR and set it as type string.
NOTE: Also ensure that you have Create workflow OUTPUT PARAMETER selected at the bottom of the menu.

Make sure to choose output parameter!
Make sure to choose output parameter!

Now to the Scripting tab of the Scriptable task, and let’s insert the code to get our CSR string from the source file created earlier.

// open the file with the CSR string
var file = new FileReader(workingFolder+"/rui.csr")
file.open()
// get the entirety of the file and assign it to output.
outputCSR = file.readAll()
// close the file
file.close()

And there it is!

In the next post, I’ll show you how to build REST API connections to Venafi with vCO that will allow you to automatically process the CSR data into a signed certificate.

Leave a Reply