Integrate HashiCorp Vault with CICD tool(Jenkins)

Sarva Bhowma
Geek Culture
Published in
6 min readFeb 2, 2022

What is Vault ?

HashiCorp Vault is designed to help organizations manage access to secrets and transmit them safely within an organization. Secrets are defined as any form of sensitive credentials that need to be tightly controlled and monitored and can be used to unlock sensitive information. Secrets could be in the form of passwords, API keys, SSH keys, RSA tokens, or OTP.

HashiCorp Vault makes it very easy to control and manage access by providing you with a unilateral interface to manage every secret in your infrastructure. Not only that, you can also create detailed audit logs and keep track of who accessed what.

Why use Vault with Jenkins?

One very common problem with keeping our secret credentials in Jenkins is how pipeline handles credentials. Whenever a pipeline obtains a secret that is scoped, there are no limitations to it on how much and in what ways the pipeline can use them. This poses a potential security threat considering the pipeline may be interacting with uncontrolled external.

The next problem with Jenkins is the use of its encryption methods. There is a static, single common master key and static single common hudson.util.Secret object. Both of these combine to encrypt our credentials. If access to our Jenkins host is compromised, we risk leaking these two keys and thus are credentials will be exposed.

This is where Vault comes to our rescue. The first thing that it did was adding another layer of authentication over Jenkins. The next advantage for it was its access control policies. We can add multiple policies to access the same secret. Then we can call it in our pipelines keeping in mind how much access we want to give. We can even do as much as defining permission of access for machines and programs. This gives us better isolation and a patterned access rules.

Below is the workflow diagram to visualize on how they comunicate each other.

Workflow diagram

Pre-requisites

  • Vault Installed.
  • Jenkins installed.
  • Enabling access to Vault requires the installation of hashicorp-vault-plugin and a running Vault instance.
  • Next, we need to decide the method of authentication we will be using for accessing it. Hashicorp provides us with multiple authentication methods which are listed below:
    AWS
    Azure
    Google Cloud
    AppRole
    GitHub
    Kubernetes
    LDAP
    TLS Certificates
    Tokens
    Username and Password
    MFA (Legacy/Unsupported)…etc..

Since our aim is to connect Jenkins to Vault, for this purpose the best way is to use AppRole.

AppRole Authentication Method

An “AppRole” represents a set of Vault policies and login constraints that must be met to receive a token with those policies. An AppRole can be created for a particular machine, or even a particular user on that machine, or a service spread across machines.

1. Create AppRole

To enable approle first, you have to add the vault url &token to authenticate with vault. In my case Im running the vault as dev, and local, hence i have given loopback address(as shown below). Below i am using my test vault root token to connect with vault:

$ export VAULT_ADDR='http://127.0.0.1:8200'
$ export VAULT_TOKEN=”s.qZXTYvG…….ecF9uoX”

Below is the command to enable the approle authentication in vault.

$ vault auth enable approle

Then, create a role to use it in Jenkins,

$ vault write auth/approle/role/jenkins-role token_num_uses=0 secret_id_num_uses=0 policies="jenkins"

Note: If you want your token and secret_it_ttl to live forever then set token_ttl and secret_id_ttl to 0.

Now we have our role created, and to login successfully, we need role ID and secret ID, to fetch these, run below commands.

$ vault read auth/approle/role/jenkins-role/role-id$ vault write -f auth/approle/role/jenkins-role/secret-id

Create a credentials in vault.(which we use it in jenkins pipeline), Here i have given test credentials.

$ vault kv put secret/dev-creds/git-pass test-git-creds=123456789

So, As of now we have created an approle and credentials in vault, but this doesnt mean that created app role can freely get the secrets(snce we have explicitly mentioned that approle to use specific policy). To read the secrets, we have to create policy and add the rules.

First, create a file to mention the policy, in my case, i have created jenkins-policy.hcl file and added the below code.

path "secret/data/dev-creds/git-pass" {
capabilities = ["read", "list"]
}

And then, create a jenkins policy with the help of this rule. Run the below command for the same.

$ vault policy write jenkins jenkins-policy.hcl

2. Install Vault Plugin & Integrate vault with Jenkins

First login to Jenkins and click on manage Jenkins and then navigate to Manage plugins.

Then click on available and type HashiCorp vault and then click on install.

After installing the plugin, Navigate to manage Jenkins and Configure system. and find the vault plugin and fill the URL and then click on add the credentilas to add the approle authentication and select kind as Vault AppRole Credentials and fill out the role ID, Secret ID, path and ID as generic name to identify and click on Add.

Vault authentication credentials configure in jenkins

And later click on advance settings to disable the ssl certfication. (In production its not recomended to disable it). (Based on these setting Jenkins actually authenticate with Vault.)

Vault plugin configure in jenkins

Now, create a Jenkins pipeline and add the below pipeline code to test the secret fetching from vault.

Pipeline configure
Pipeline Output

Thats it, as you see it’s connecting to vault and fetching the value. since it’s secret its not pasting the actual value on the output.

Note:
If there is an error at any step, we will see a message for access denied, and the environment variable will print null. (Below is the screenshot of the error)

Failed vault connection pipeline output

Conclusion:

As you can see, integrating vault into the Jenkins pipeline is not so complex, if you do it properly and spend some time to understand exactly what engine and version you are using before proceeding. I hope this post was helpful to you and now the integration process seems more obvious.

Thank you for reading.

--

--