Mocking Hashicorp vault in Go

送分小仙女□ 提交于 2020-05-28 11:38:40

问题


Is there an easy way to mock Hashicorp vault in go tests ?

I created a service in Go that accesses Vault, and would like to create proper testing for it.

I didn't find a simple solution I like (like moto in python). I also tried using a vault in dev mode in docker (take the system test route) but I have trouble writing to it via API. Ideas ?


回答1:


Is there an easy way to mock HashiCorp Vault in Go tests?

Don't. Use the real thing! HashiCorp helpfully provides utility functions for starting a server on the fly1. This makes your tests much more useful, and can often serve as an actionable guide for developers on how to setup local development servers too.

Here is a very basic example. The testing framework is very flexible (which also makes it fairly complicated). Refer to the package documentations for more options, including running multiple servers in HA mode. I found Vault's own test cases very useful when setting up more complicated scenarios.

package main

import (
    "net"
    "testing"

    "github.com/hashicorp/vault/api"
    "github.com/hashicorp/vault/http"
    "github.com/hashicorp/vault/vault"
)

func TestVaultStuff(t *testing.T) {
    ln, client := createTestVault(t)
    defer ln.Close()

    // Pass the client to the code under test.
    myFunction(client)
}

func createTestVault(t *testing.T) (net.Listener, *api.Client) {
    t.Helper()

    // Create an in-memory, unsealed core (the "backend", if you will).
    core, keyShares, rootToken := vault.TestCoreUnsealed(t)
    _ = keyShares

    // Start an HTTP server for the core.
    ln, addr := http.TestServer(t, core)

    // Create a client that talks to the server, initially authenticating with
    // the root token.
    conf := api.DefaultConfig()
    conf.Address = addr

    client, err := api.NewClient(conf)
    if err != nil {
        t.Fatal(err)
    }
    client.SetToken(rootToken)

    // Setup required secrets, policies, etc.
    _, err = client.Logical().Write("secret/foo", map[string]interface{}{
        "secret": "bar",
    })
    if err != nil {
        t.Fatal(err)
    }

    return ln, client
}

1 They provide test servers for all of their projects, not just Vault. Mitchell Hashimoto explained the rational in his talk on advanced testing.




回答2:


Because Go is a statically typed language we have to know the type of things at compile time. So to do this type of independent testing we need to create boundaries in our code that make logical sense in terms of testing.

Interfaces are created in Go to define these boundaries, so in this sense you want to create an interface between you and this third party library so that you can replace the inputs and outputs of the libraries functions/methods/types with ones that you can control and have defined conditions so that you can test how your code behaves to outputs or conditions of the third party.

See the below for examples of interfaces.

https://gobyexample.com/interfaces

if you share some example code perhaps we can be a little more specific and give you some code examples.




回答3:


One super important thing to note:

TestCoreUnsealed doesn't use the regular KV backend, instead it uses a PassthroughBackend to essentially mock the kv behavior.

follow this issue, i've spent 4 days debugging this

https://github.com/hashicorp/vault/issues/8440



来源:https://stackoverflow.com/questions/57771228/mocking-hashicorp-vault-in-go

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!