If you are getting into infrastructure as code (IaC), no doubt you have at least experimented with Hashicorp Terraform. Terraform is a very human-readable language that allows easily provisioning infrastructure across a wide range of environments, from on-premises to the cloud. One of the first hurdles you will encounter with your infrastructure-as-code endeavors is how to deal with credentials in a secure way. Using Terraform Vault provider with VMware vSphere.
Storing Terraform credentials in plain text
There are many posts out there, including some I have written that demonstrate how to interact with vSphere environments with Terraform code and show how you can connect to your vSphere environment by hard coding credentials in a variables.tf file. However, in reality, you never want to hard code credentials in plaintext view for obvious security reasons. In fact, often, you will see the SSO administrator credentials placed in clear text to run Terraform code.
While this is easy (I have done this many times), I am trying to get in a better routine, even with the home lab of correctly dealing with credentials in a safe and secure way. Hopefully, my thoughts here will help to stir others to have better password hygiene in their infrastructure as code.
What is Hashicorp Vault?
What is Hashicorp Vault? I will let Hashicorp define Vault for you. According to the Adopting Hashicorp Vault resource:
“HashiCorp Vault is a secrets management solution that brokers access for both humans and machines, through programmatic access, to systems. Secrets can be stored, dynamically generated, and in the case of encryption, keys can be consumed as a service without the need to expose the underlying key materials.”
Using Terraform Vault Provider with VMware vSphere
Terraform interacts with Hashicorp Vault by way of a Terraform provider. What is a provider? A Terraform provider allows Terraform to interact with remote systems.
You can learn the details of the Terraform Vault provider on the official Terraform registry page here:
So essentially, we will be using the Terraform provider to connect to a Hashicorp Vault server, and pull credentials using the token authentication method. We will also look at how to hide the token used to connect to your Vault server to obtain the vSphere credentials.
There are several ways to connect to Vault as described in the official registry page. The AppRoles are extremely powerful and I will be exploring those more in future posts. However, in this post, again we will be using he simple token approach to authenticate to the Vault server, pull the vCenter Server password and use this to run our Terraform vSphere provider code.
Setting up Hashicorp Vault for vSphere credentials
Take a look at my post here on how to install and configure Hashicorp Vault on an Ubuntu Server installation.
Once you have your installation ready to go, you simply need to create a key value store type credential in Vault. The path I created is simply vcenter/vcenterpass/password with the password actually holding the password value.
After you have your key value store setup in Vault, we can use an access token to access the keystore. How do you get a token? Login to your Vault instance and use the following command:
vault token create
vault token create -tls-skip-verify (if self-signed cert)
Now that we have the token generated in Hashicorp Vault, you may wonder. How do we use the token in code without exposing it? Actually, the way I am doing this is setting an environment variable by means of the TF_VAR environment variable. When you use TF_VAR in front of the variable name you set, Terraform reads these and understands the values with each Terraform run. If you are running on a Windows machine, you can use the setx command to set the TF_VAR_vault token variable. This will make more sense when you look at the code below. The /m switch tells it to set the variable as a global variable instead of a local variable. As a note here, you need to make sure you set the variable in the command environment you will be using to run Terraform. If you are using PowerShell Core to run the Terraform terminal, use the same environment to et the variable.
The great thing about using an environment variable, is the token is not exposed in clear text on disk or stored in a variables file.
Declaring the vault_token
In your variables.tf file or your main.tf, you will have to declare the variable, but we can do that will just an empty block:
variable "vault_token" {}
Now that we have the environment variable set and the variable declared in Terraform code, we can connect to the Vault provider using the Terraform code.
Connecting to the Hashicorp Vault Provider in Terraform
In your Terraform code, you can set the Terraform Vault provider connection like below. As you can see, we are authenticating to the Vault server using the vault_token variable. This will pull from the environment variable set above.
provider "vault" {
address = "https://vault.cloud.local:8200/"
skip_tls_verify = true
token = var.vault_token
}
Terraform Vault Data Blocks
Now that we have a connection to the Vault server, we can use data blocks to query the Vault server for the vCenter credentials needed. Also, below, I am using a data block for pulling the Windows password that is set in the customization section of the Terraform code.
data "vault_generic_secret" "vcenterpass" {
path = "vcenter/vcenter_pass"
}
data "vault_generic_secret" "windows_pass" {
path = "windows/windows_pass"
}
How do we use this information to connect to vCenter Server? In your vSphere provider, for the password, you will use the following code. Note you will customize the below to match your data blocks defined for the vCenter password.
data.vault_generic_secret.vcenterpass.data["password"]
Note, even though the Terraform vSphere provider is listed first, Terraform is smart enough to know when it runs, it needs to get the credentials from Vault and use these for the vSphere provider connection.
Also, in my code I am simply coding the vCenter username and vCenter Server is plain text, however, there is nothing stopping you from hiding these values as well and storing these in Hashicorp Vault as well.
Terraform Init, Plan, and Apply
Before you run your Terraform code containing the Vault and vSphere providers, make sure you run the Terraform Init command to pull down the provider plugins needed to run the Terraform code with the Vault and vSphere providers.
Once you have the plugins pulled, you should be able to run your Terraform plan and validate the code is able to connect successfully to vCenter Server. If you receive an error about variable not being defined, make sure you have defined the variable in your variables.tf file.
Wrapping Up
Using Terraform Vault Provider with VMware vSphere is a great way to secure your infrastructure as code to interact with vCenter in a secure way. While you can certainly use plain text passwords, this is extremely dangerous to do as flat files with credentials can provide attackers with everything they need to compromise your environment. Hopefully, the steps laid out in the post will help others who may be struggling to get up and running with Terraform, Vault, and vSphere automation.
0 Comments