Being a data company, Lusha takes security issues very seriously. This is why we use Hashicorp’s Vault.

What is Vault?

Vault by HashiCorp is an identity-based secret and encryption management system. It helps manage credentials effectively.
A modern system requires access to a multitude of secrets: database credentials, API keys for external services, etc.
Vault helps store your secret securely, define dynamic secrets, lease, renew and revoke secrets.

Authentication Methods

Vault implements various authentication methods in order to assign identity and a set of policies to a user.
Some of Its auth methods includes: AppRole, Kubernetes, AWS, Github, Google Cloud, JWT/OIDC,  Kerberos, and Okta. For the sake of this article, I’ll focus on K8S auth and show you how to implement Vault’s K8S auth with Golang,

Kubernetes Authentication

In this method, we will leverage the Kubernetes Service Account Token.
This authentication method makes it easy to introduce a Vault token into a Kubernetes Pod.

In the section below we will implement a function that will authenticate to vault using K8S auth and will help us implement secrets fetching later on.

Let’s begin by defining some constants based on our vault environment and configuration.
Once that is done, we can initialize an HTTP client that will use us to authenticate to vault.
We’ll use our new HTTP client to create a vault client, also configuring the address to our vault server.
We are using vault’s command package and importing vaultKube to create a new kubernetesAuthMethod while using our predefined mountPath and KubeTokenRole.
Using the authed.Authenticate method we’re able to read our token from the default service account path (that can also be configured while creating kubernetesAuthMethod), using the returned token we’ll send an auth request to vault with the vc.Logical().Write method, this method returns a client token which we will set on our vaultClient.

Congrats! We’re now ready to observe our functioning vault client that will let us fetch secrets from vault.

But the above process is wrapped in sync.Once. To ensure this operation only occurs once, we need to only do it the first time we request the client. After this initial time, each call to the GetVaultClient function will only return the already authenticated client without authenticating again.

Getting a Secret

Now, after authenticating using K8S method we can start fetching our secrets.
Let’s see how it’s done and implement a helper function for it.

So what do we have here?

We’ve got two continuous functions: GetVaultSecret, which gets a path to a secret and returns it, and extractSecret, which casts vault’s response and assumes we are using JSON secret values. If you use a string of secrets, you can just replace the cast.

Whenever we need a secret, we’ll call GetVaultSecret with the desired secret path.
As we can see, this function calls the GetVaultClient function we implemented before, then reads the requested path from vault and pairs it using the extractSecret function that casts the response as explained above.

If everything goes according to plan, we’ve got our secret! 🎉

Using Hashicorp’s Vault to manage secrets is highly recommended and will make your secret management easier. I hope I helped you with implementing your first Vault integration in golang.

Have fun managing your secrets!

5 2 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Developer? Join Lusha - Apply today!