[HashiCorp Vault] 2022 Review - How to integrate Harness with Vault using Vault Agent (Delegate)

Introduction

This tutorial is a detailed walkthrough to help you to adopt Vault Agent in your integration between Harness and HashiCorp Vault (as a Secrets Manager).

To make this simple, I’ll use a Shell Script Delegate and start the Vault Agent as a Service.

I’ve created another tutorial for K8s Delegates, but it’s a bit more complex.
For that approach, my suggestion is to use a sidecar container to run Vault Agent and then we share volumes between the two containers on the Delegate StatefulSet (in the future Deployment).

Anyway, the focus here is to teach you about the Vault Agent approach itself, so let’s keep it simple.

IMPORTANT: It’s super important to keep in mind that the Vault Agent IS NOT a component of Harness. It’s inside HashiCorp’s Kingdom, ok?
At the end of the day, our Delegate only needs to be able to reach for a sink file containing a good token.

Buckle up! :rocket:

Step 1 - Installing Vault Agent in your Delegate (Shell Script for this tutorial)

Please, just install a vault binary on your Delegate. You can also use Delegate Profiles to achieve that.
It’s straightforward: Downloads | Vault by HashiCorp

For example, this is what I did on my Ubuntu Delegate:

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install vault

Step 2 - Configuring an ACL Policy, and mapping it to a Role (I’ll use AppRole + SecretId).

You can do this with your Vault Admins, if you prefer. In my case, I’ll just enable AppRole and configure it.

I just want to draw attention to my ACL Policy. It’s good for a v2 Secrets Engine.

The first thing is to enable the AppRole:

vault auth enable approle

And I’ll define a very good ACL Policy for this Lab purposes. Please note that it looks overkill, but it is pertinent to a single kv Secrets Engine. Please refer to this to better understand it: Add a HashiCorp Vault Secrets Manager - Harness.io Docs

So, this is my ACL Policy:

path "kv/*" {
capabilities = ["create", "list", "read", "update", "delete"]
}

path "kv" {
   capabilities = ["create", "list", "read", "update", "delete"]
}

# Alow token to renew itself
path "auth/token/renew-self"
{
 capabilities = ["read", "update"]
}

# List existing secrets engines.
path "sys/mounts"
{
  capabilities = ["read"]
}

So, it’s time to map that Policy to one very nice AppRole.
I will avoid creating SecretID with TTL, I need to keep this simple.

This snippet should be enough:

export VAULT_ADDR=<YOUR_VAULT_ADDR>
export VAULT_TOKEN=<VAULT_ADMIN_TOKEN>

vault write auth/approle/role/harness-tutorial \
    secret_id_ttl=0 \
    token_num_uses=0 \
    token_ttl=60m \
    token_max_ttl=120m \
    secret_id_num_uses=0 \
    token_policies=harness_tutorial_v2_policy

Finally, let’s retrieve both RoleID + SecretID:

# another approach:
# export ROLE_ID=$(vault read -field=role_id auth/approle/role/harness-tutorial/role-id)
# export SECRET_ID="$(vault write -f -field=secret_id auth/approle/role/harness-tutorial/secret-id)"

vault read -field=role_id auth/approle/role/harness-tutorial/role-id
vault write -f -field=secret_id auth/approle/role/harness-tutorial/secret-id

Step 3 - Configuring HCL Config file for your Vault Agent (that is running on the Delegate)

I’ll keep my config file here:

sudo touch /opt/vault/config.hcl
sudo chown vault.vault /opt/vault/config.hcl

You can ask your Vault Admin to review that with you. I like to keep both RoleId + SecretId on files, and refer to them on the configuration.

This is what works like a charm for me:

pid_file = "/opt/vault/.pidfile"

vault {
  address = "http://ec2-54-23.<EXAMPLE>:8200"
  tls_skip_verify = true
  retry {
    num_retries = 5
  }
}

auto_auth {
  method "approle" {
    config = {
      role_id_file_path = "/opt/vault/.roleid"
      secret_id_file_path = "/opt/vault/.secretid"
      remove_secret_id_file_after_reading = false
    }
}

sink "file" {
    config = {
      path = "/opt/vault/.sinkToken"
    }
  }
}

cache {
  use_auto_auth_token = true
}

listener "tcp" {
  address = "127.0.0.1:8100"
  tls_disable = true
}

Then let’s make sure the required files are there:
image

Finally, you can verify that this is working by simply running it manually now:

vault agent -config config.hcl

And we test the token real quick:

# export the brand new (while ttl permits) token, generated by Vault Agent
export VAULT_TOKEN=$(cat /opt/vault/.sinkToken)

# Check the list Secrets Engines capability (I'd do this if I were you)
vault token lookup

# Try to take a peek into your desired Secrets Engine (kv on my case):
vault kv list kv/

Step 4 - Let’s create a Daemon!

There’s no official way to run and enable the Vault Agent , and that’s why I could have used nohup in this brief tutorial. But, if I’m responsible for deploying it in Prod, and considering that I will run this in a good old Linux env, I’d create a Systemd Service.

To be honest, I’d use a K8s Delegate + Vault Agent sidecar sharing the volumes. But let’s keep this simple.

Let’s work on this file:

vim /etc/systemd/system/vault-agent.service

Then we configure our very distinguished Vault Agent “Service”:

[Unit]
Description="Vault Agent to serve Tokens"

[Service]
User=root
WorkingDirectory=/opt/vault
ExecStart=/usr/bin/vault agent -config=/opt/vault/config.hcl
Restart=always

[Install]
WantedBy=multi-user.target

And then the final Linux trick:

sudo systemctl daemon-reload
sudo systemctl start vault-agent
sudo systemctl status vault-agent
sudo systemctl enable vault-agent

It looks sharp!

Step 5 - Time to configure the Secrets Manager on Harness!

I will use the same Policy to list the available Secrets Engines. So, the head of the configuration should look like this one. Please notice that I’m using a Delegate Selector that will isolate my Shell Script Delegate.

So, now comes the trick. Let’s ask Harness to refer to the sink file from now on:
image

Looks good, right? Let’s add a Secret and close this tutorial forever!!!
image

Ha! We are good!

image

image

Further reading:

Tags:

<cloud: aws, gcp, azure>
<function: ci,cd>
<role: swdev,devops,secops,itexec>
<type: howto, experts>
<category: gitops, vault, secrets>

1 Like