Skip to content

scribd/vaulttest

master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 

vaulttest

Circle CI

Library for spinning up test instances of Hashicorp Vault for use in integration tests locally and in CI systems.

Hashicorp Vault is an awesome tool, but if your job is managing it, you need more than pointing and clicking in a UI, or running vault commands against the server.

A much better way is to write some code that instruments your Vault in a predictable manner, but how does one test said code?

What's really needed is a test Vault or better yet a fleet of them to test changes in parallel.

Unfortunately Hashicorp Vault's source code is not organized/ exported in a way to make it's internal api easily adapted to a fully code defined, in memory Vault dev server.

What we can do, however, is have this package spin one up- provided the vault binary is on the system somewhere.

The vaulttest package will find a free port, spin up vault in dev mode on that port, allow you to do your tests against it, and shut it down politely once you're done.

Prerequisites

Usage

Include the following in your test code:

var testServer *vaulttest.VaultDevServer
var testClient *api.Client

func TestMain(m *testing.M) {
    setUp()

    code := m.Run()

    tearDown()

    os.Exit(code)
}

func setUp() {
    port, err := freeport.GetFreePort()
    if err != nil {
        log.Fatalf("Failed to get a free port on which to run the test vault server: %s", err)
    }

    testAddress := fmt.Sprintf("127.0.0.1:%d", port)

    testServer = vaulttest.NewVaultDevServer(testAddress)

    if !testServer.Running {
        testServer.ServerStart()
        client := testServer.VaultTestClient()

        // set up some secret engines
        for _, endpoint := range []string{
            "prod",
            "stage",
            "dev",
        } {
            data := map[string]interface{}{
                "type":        "kv-v2",
                "description": "Production Secrets",
            }
            _, err := client.Logical().Write(fmt.Sprintf("sys/mounts/%s", endpoint), data)
            if err != nil {
                log.Fatalf("Unable to create secret engine %q: %s", endpoint, err)
            }
        }

        // setup a PKI backend
        data := map[string]interface{}{
            "type":        "pki",
            "description": "PKI backend",
        }
        
        _, err := client.Logical().Write("sys/mounts/pki", data)
        if err != nil {
            log.Fatalf("Failed to create pki secrets engine: %s", err)
        }

        data = map[string]interface{}{
            "common_name": "test-ca",
            "ttl":         "43800h",
        }
        
        _, err = client.Logical().Write("pki/root/generate/internal", data)
        if err != nil {
            log.Fatalf("Failed to create root cert: %s", err)
        }

        data = map[string]interface{}{
            "max_ttl":         "24h",
            "ttl":             "24h",
            "allow_ip_sans":   true,
            "allow_localhost": true,
            "allow_any_name":  true,
        }
        
        _, err = client.Logical().Write("pki/roles/foo", data)
        if err != nil {
            log.Fatalf("Failed to create cert issuing role: %s", err)
        }

        data = map[string]interface{}{
            "type":        "cert",
            "description": "TLS Cert Auth endpoint",
        }

        _, err = client.Logical().Write("sys/auth/cert", data)
        if err != nil {
            log.Fatalf("Failed to enable TLS cert auth: %s", err)
        }
        
        ... Do other setup stuff ...
        
        testClient = client
    }
}

func tearDown() {
    if _, err := os.Stat(tmpDir); !os.IsNotExist(err) {
        os.Remove(tmpDir)
    }

    testServer.ServerShutDown()
}

func TestNewNamespace(t *testing.T) {
    path := "dev/foo/bar"
    secret, err := testClient.Logical().Read(path)
    if err != nil {
        log.Printf("Unable to read %q: %s\n", path, err)
        t.Fail()
    }
    
    if secret == nil {
        log.Print("Nil Secret")
        t.fail() 
    }
    
    assert.True(t, secret.Data["foo"].(string) == "bar", "Successfully returned secret")
}

About

Integration test Vault code locally!

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages