/vault-secret-id-receiver

Primary LanguageGoMozilla Public License 2.0MPL-2.0

vault-secret-id-receiver

This library is part of an application secrets management solution based on HashiCorp Vault. It aims to eliminate the problem of having the application store a credential for access to the secrets vault.

The AppRole authentication method is used to access the vault. An application can use this library to wait for a wrapped secret ID to be posted to a ReST interface. Once received the library unwraps the secret ID and uses it to login and retrieve a client token. The ReST interface is then closed down. The application can use the logged in client to retrieve secrets from the vault. The library also manages the ongoing automatic renewal of the client's login token.

Methods are also available to be able to simply create, overwrite and read secrets in the vault. These use the key/value v2 store

GoDoc

Go Report Card Build Status

Configuration

The library has a configuration struct which the application can chose how to populate. For example, by loading from a JSON file.

type Config struct {
	VaultURL    string
	MaxRetries  int
	CACertFile  string
	ClientCert  string
	ClientKey   string
	ReceivePort int
	RoleID      string
}
  • VaultURL - the URL of the vault server (eg https://vault.example.com:8200).
  • MaxRetries - sets the number of retries that will be used in the case of certain errors against the vault.
  • CACertFile - the CA certificate, to be trusted, which signed the vault URL's certificate.
  • ClientCert - the certificate that the application will use to communicate with the vault and on the ReST interface that listens for the wrapped secret ID.
  • ClientKey - the private key of the ClientCert.
  • ReceivePort - the TCP port the library's ReST interface will listen on to which the wrapped secret ID should be posted.
  • RoleID - the role ID for the AppRole authentication method.

Usage

Below are code snippets for how to use the library

Create the vault client and wait for the secret ID to be posted.
    import "github.com/jcmturner/vault-secret-id-receiver/vaultclient"

    l := log.New(os.Stderr, "Vault Client: ", log.Ldate|log.Ltime|log.Lshortfile)
    c, err := New(cfg, l)
    if err != nil {
    	panic(fmt.Sprintf("could not create vault client: %v", err))
    }
    err = c.WaitForSecretID()
    if err != nil {
    	panic(fmt.Sprintf("error waiting for secret ID: %v", err))
    }

c.WaitForSecretID() blocks until the secret ID has been posted. Do this at the beginning of the initial start of the application.

Create, read and update secrets.
    // Create secret
    location := "mysecret"
	err := c.CreateSecret(location, map[string]string{
		"key1": "value1",
		"key2": "value2",
	})
	if err != nil {
	    return fmt.Errorf("failed to create new secret: %v", err)
	}
	
	// Read secret
	s, err := c.ReadSecret(location, 0)
	if err != nil {
		return fmt.Errorf("failed to read secret: %v", err)
	}
	
	// Overwrite an existing secret
	err = c.OverwriteSecret(location, map[string]string{
		"key1": "newvalue",
	})
	if err != nil {
		return fmt.Errorf("failed to update secret: %v", err)
	}

The secret returned from the ReadSecret method is a HashiCorp Vault API Secret struct. Values can be accessed like this:

	one := s.Data["data"].(map[string]interface{})["key1"].(string)

Posting the Secret ID

The secret ID should be posted by another process to the ReceivePort. The secret ID needs to be wrapped and is posted in a json payload as below:

{
  "secret_id": "wrapped-secret-id-string"
}