DEV Community

Ankit malik
Ankit malik

Posted on

Golang: Authenticate Your vault sdk with Kubenetes

Why we should authenticate vault with Kubenetes

When are running our application in Kubenetes pods then we can directly connect vault and pod which will create a token inside the pod at specific location.
So to access the data from vault we need to generate the token with Kubernetes token.
Benefit: The main benefit of this method is that we don't need the static token for vault.

Example

package main

import (
    "context"
    "encoding/json"
    "fmt"

    "github.com/go-resty/resty/v2"
    "github.com/hashicorp/go-hclog"
    "github.com/hashicorp/vault/command/agent/auth"
    vaultKube "github.com/hashicorp/vault/command/agent/auth/kubernetes"
)

// const can be created for these variables
var kubeTokenVaulPath = "{{your kubernetes vault token file path}}"
var KubeTokenRole = "{{your kube token role}}"
var vaultAddr = "{{your vault address}}"
var mountPath = "/v1/auth/{{path for Kv}}"

type VaultAuth struct {
    ClientToken string `json:"client_token"`
    Accessor    string `json:"accessor"`
}
type CredOutput struct {
    Auth VaultAuth `json:"auth"`
}

func main() {
    appLogger := hclog.New(&hclog.LoggerOptions{
        Name:  "my-app",
        Level: hclog.LevelFromString("DEBUG"),
    })

    auth, err := vaultKube.NewKubernetesAuthMethod(&auth.AuthConfig{
        Logger:    appLogger,
        MountPath: vaultAddr + mountPath,
        Config: map[string]interface{}{
            "role":       KubeTokenRole,
            "token_path": kubeTokenVaulPath,
        },
    })

    if err != nil {
        panic(err)
    }

    // this functions returns
    // path which is the url where we need to request
    // header it will generate the headers required for the request
    // body - it will generated the body token request
    path, header, body, err := auth.Authenticate(context.Background(), nil)
    if err != nil {
        panic(err)
    }
    fmt.Println(path, header, body)

    // I am using Resty because direct vault request client was not working
    client := resty.New()
    resp, err := client.R().
        SetBody(body).
        Post(path)
    if err != nil {
        panic(err)
    }
    fmt.Println("output", string(resp.Body()))

    // creds will be the object where we will get
    // the token generated for vault to access data
    creds := CredOutput{}
    json.Unmarshal(resp.Body(), &creds)
    fmt.Println("final obj", creds)
}

Enter fullscreen mode Exit fullscreen mode

We need to define these 4 params in order to generate the token for vault from Kubernetes pods token.

var kubeTokenVaulPath = "{{your kubernetes vault token file path}}"
var KubeTokenRole = "{{your kube token role}}"
var vaultAddr = "{{your vault address}}"
var mountPath = "/v1/auth/{{path for KV}}"
Enter fullscreen mode Exit fullscreen mode

mountPath: will be used to generate the token path.
Vault have default path with the name secrets for KV path

I am Resty client because vault's NewRequest was not working.
Look at how we can use vault's inbuild rawRequest method but wasn't working for me.
Not Recommended As of Now

req := client.NewRequest("POST", path)
req.SetJSONBody(output)
resp, err := client.RawRequest(req)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)