Shifna Zarnaz

Automating Vault Key Management in Kubernetes with Golang

Table of Contents:

  • 1. Introduction
  • 2. Prerequisites
  • 3. Code Overview

    • Import Statements
    • Vault struct
    • Generating Unseal Keys
    • Unsealing the Vault
    • Configuring the Kubernetes Client
    • Storing Keys in Kubernetes Secrets
    • Retrieving Keys from Kubernetes Secrets
    • Monitoring and unsealing vault automatically

  • 4. Conclusion

1. Introduction

This blog post explores an automated approach to manage Vault keys in a Kubernetes environment using Golang. It covers how to generate, store, and retrieve Vault unseal keys and root tokens in Kubernetes Secrets. The sample code provided demonstrates the implementation of this approach, integrating the HashiCorp Vault API with the Kubernetes client-go library.


Before proceeding with the implementation, make sure you have the following prerequisites in place:

  • Basic knowledge of Go programming language
  • Access to a Kubernetes cluster
  • A running Vault server in the Kubernetes cluster
  • Go installed on your local machine
  • A running HashiCorp Vault server
  • kubectl command-line tool installed and configured to communicate with the Kubernetes cluster
  • Basic understanding of Vault and its concepts

Code Overview

The code provided is written in Go and consists of several components that work together to automate the unsealing of a Vault server in a Kubernetes cluster and to store the keys in k8s secret. Let’s dive into the code and understand its key components.

Import Statements

The code starts by importing necessary packages, including the Vault API, Kubernetes API, and utility packages.

                    import (
                      corev1 ""
                      metav1 ""

Vault Struct

The vault struct holds a client object from the Vault API and provides methods for interacting with the Vault server. This struct will be used to generate unseal keys, unseal the Vault, and store/retrieve the keys from Kubernetes secrets

                    type vault struct {
                      client *api.Client

Generating Unseal Keys

Generates the required number of unseal keys and the root token using the Vault API. These keys are later stored in a Kubernetes Secret.

                    func (v vault) GenerateUnsealKeysFromVault() ([]string, string, error) {
                      res := &api.InitRequest{
                       SecretThreshold: 2,
                       SecretShares:    3,
                      unsealKeys := []string{}
                      key, err := v.client.Sys().Init(res)
                      if err != nil {
                       fmt.Println("Error while initializing ", err)
                      for _, key := range key.Keys {
                       fmt.Println("Key is ", key)
                       unsealKeys = append(unsealKeys, key)
                      rootToken := key.RootToken
                      fmt.Println("Root Token is ", rootToken)
                      fmt.Print("Unsealed keys are generated")
                      return unsealKeys, rootToken, err

Unsealing the Vault

The Unseal() method takes a slice of unseal keys and iterates over them to unseal the Vault server. If any error occurs during the unsealing process, it returns the error.

                    func (v vault) Unseal(keys []string) error {
                      flag := true
                      for _, key := range keys {
                       _, err := v.client.Sys().Unseal(key)
                       if err != nil {
                        flag = false
                        fmt.Println("Error while unsealing", err)
                        return err
                      if flag {
                      return nil

Configuring the Kubernetes Client

The Config() function reads the kubeconfig file and creates a Kubernetes clientset that will be used to interact with the Kubernetes API.

                    func Config() *kubernetes.Clientset {
                      var kubeconfig string
                      if home := homedir.HomeDir(); home != "" {
                       kubeconfig = filepath.Join(home, ".kube", "config")
                      config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
                      if err != nil {
                      clientset, err := kubernetes.NewForConfig(config)
                      if err != nil {
                       fmt.Println("Error while creating clientset", err)
                      return clientset

Storing Keys in Kubernetes Secrets

The Storekeys() method generates unseal keys and the root token using the GenerateUnsealKeysFromVault() method. It then creates a Kubernetes secret with the generated keys and returns the values. This function utilizes the Kubernetes clientset created in the Config() function.

                    func (v vault) Storekeys(nameSpace string, SecretName string) []string {
                      clientset := Config()
                      var values []string
                      namespace := nameSpace//namespace 
                      secretName := SecretName
                      // Retrieve the secret with the given name
                      unsealKeys, rootToken, _ := v.GenerateUnsealKeysFromVault()
                      stringData := make(map[string]string)
                      for i, value := range unsealKeys {
                       key := fmt.Sprintf("key%d", i+1)
                       stringData[key] = value
                       values = append(values, value)
                      key := "roottoken"
                      stringData[key] = rootToken
                      values = append(values, rootToken)
                      newSecret := &corev1.Secret{
                       ObjectMeta: metav1.ObjectMeta{
                        Name:      secretName,
                        Namespace: namespace,
                       StringData: stringData,
                      createdSecret, err := clientset.CoreV1().Secrets(namespace).Create(context.TODO(), newSecret, metav1.CreateOptions{})
                      if err != nil {
                       fmt.Printf("Failed to create secret: %v\n", err)
                      fmt.Printf("Secret '%s' created in namespace '%s'\n", createdSecret.Name, createdSecret.Namespace)
                      return values

Retrieving Keys from Kubernetes Secrets

The RetrieveKeys() function retrieves the previously stored unseal keys and root token from the Kubernetes Secret. It decrypts the Secret's data and returns the keys as a slice of strings.

                    func (v vault) RetrieveKeys(nameSpace string, SecretName string) []string {

                      var values []string
                      clientset := Config()
                      namespace := nameSpace // Namespace where you want to create the Secret
                      secretName := SecretName
                      secret2, err := clientset.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
                      if err != nil {
                       fmt.Println("Error while getting secret", err)
                      for key, value := range secret2.Data {
                       if key == "roottoken" {
                        break // Skip the last element
                       fmt.Printf("Retrieved value for  %s: %s\n", key, value)
                       keys := string(value)
                       values = append(values, keys)
                       // fmt.Println("Key is ", keys)
                      fmt.Printf("Secret '%s' found in namespace '%s'\n", secret2.Name, secret2.Namespace)
                      // Use the secret as needed
                      return values

Monitoring and Unsealing Vault Automatically:

The startMonitoringService() function continuously monitors the Vault server's seal status. If the server is not initialized, it generates the required keys and token and stores them in a Kubernetes Secret. If the server is sealed, it retrieves the keys from the Secret and unseals the Vault. This automated process ensures the Vault remains operational without manual intervention.

                    func startMonitoringService() {

                      client, err := api.NewClient(&api.Config{
                       Address: "",
                      if err != nil {
                       fmt.Println("Error while connecting to client", err)
                      vault := vault{
                       client: client,
                      for {
                       status, err := vault.client.Sys().SealStatus()
                       if err != nil {
                        fmt.Println("Error while sealing", err)
                       if !status.Initialized {
                        fmt.Println("Vault server is not initialized")
                        // keys,_,_:=vault.GenerateUnsealKeysFromVault()
                        keys := vault.Storekeys("namespace-name", "secret-name")
                        err := vault.Unseal(keys)
                        if err != nil {
                         fmt.Println("Error is", err)
                        fmt.Printf("Key is Stored Successfully")
                       if status.Sealed {
                        log.Printf("Vault server is sealed")
                        keys := vault.RetrieveKeys("namespacename", "secret-name")
                       // Sleep for a given interval before the next check
                       time.Sleep(1 * time.Minute)

Here replace the namespacename and secret-name with the required namespace and secret name.


In this blog post, we explored how to automate the management of Vault keys in a Kubernetes environment using Golang. We covered the process of generating, storing, and retrieving Vault unseal keys and root