caddy_vault_storage

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 20, 2024 License: Apache-2.0 Imports: 19 Imported by: 0

README

A storage module for Caddy that uses HashiCorp Vault as backend

This module supports to configure multiple Vault servers to ensure high availability. If a request on one configured address failes, another will be tried. This is useful, if you don't have a load-balancer for your Vault cluster or you are using Caddy as a load balancer for it.

If you run Caddy inside a Nomad cluster, you can use Nomad to issue Vault tokens for it.

Notice

A running Vault instance/cluster with an enabled KVv2 mount is required for using this module. At startup a check for required capabilities on the configured secrets path will be performed and error messages will be shown with the missing capabilties, if any. The following capabilities must be granted:

path "kv/metadata/caddy/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

path "kv/data/caddy/*" {
  capabilities = ["create", "read", "update"]
}

path "kv/delete/caddy/*" {
  capabilities = ["create", "update"]
}

Replace kv with your KVv2 mount path and caddy with your secrets path prefix, if you are using different values than the defaults ones.

Usage

To build caddy with this module run xcaddy build --with github.com/gerolf-vent/caddy-vault-storage.

Configuration

This module is based on the Vault api client, so it supports most of it's environment variables. The environment variables VAULT_ADDR and VAULT_MAX_RETRIES are ignored.

Name Type Default Description
addresses []string None One or more addresses of Vault servers (on the same cluster)
token_path string $VAULT_TOKEN environment variable Local path to read the access token from. Updates on that file will be detected and automatically read.
secrets_mount_path string "kv" Path of the KVv2 mount to use
secrets_path_prefix string "caddy" Path in the KVv2 mount to use
max_retries int 3 Limit of connection retries after which to fail a request
lock_timeout int 60 Timeout for locks (in seconds)
lock_check_interval int 5 Interval for checking lock status (in seconds)
Example

Run caddy run --config server.json with the following configuration as server.json:

{
	"storage": {
		"module": "vault",
		"addresses": ["https://server1", "https://server2", "https://server3"],
		"token_path": "./vault_token"
	},
	"logging": {
		"logs": {
			"default": {
				"level": "DEBUG"
			}
		}
	},
	"apps": {
		"http": {
			"servers": {
				"example": {
					"listen": [":8000"],
					"routes": [
						{
							"match": [{
								"host": ["localhost"]
							}],
							"handle": [{
								"handler": "static_response",
								"body": "Hello, world!"
							}]
						}
					]
				}
			}
		}
	}
}

Testing

A running vault instance/cluster with at least two distinct addresses is required to run all of the tests. The tests can be performed by VAULT_STORAGE_ADDR="https://server1,https://server2" VAULT_TOKEN="..." go test. Extensive logging is enabled to debug any errors.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrAllServersUnavailable = errors.New("All servers are unavailable")
View Source
var ErrClientNotInitialized = errors.New("Client is not initialized")
View Source
var ErrInvalidResponse = errors.New("Couldn't process an invalid response")
View Source
var ErrInvalidValue = errors.New("Data in this key has an invalid value")
View Source
var ErrNoServersConfigured = errors.New("No servers configured")
View Source
var ErrRetriesExceeded = errors.New("Connection retry count exceeded")

*

  • Errors

Functions

This section is empty.

Types

type LockInfo

type LockInfo struct {
	Created  time.Time
	Version  int // Version number of the current holded lock (required for check-and-set)
	IsLocked bool
}

*

  • Data structure for lock information

type VaultStorage

type VaultStorage struct {

	// One or more address(es) to Vault servers on the same cluster. (At least one address is required.)
	Addresses []string `json:"addresses"`

	// Local path to read the access token from. Updates on that file will be
	// detected and automatically read. (As fallback the the environment
	// variable "VAULT_TOKEN" will be used, but it will only be read once on
	// startup.)
	TokenPath string `json:"token_path,omitempty"`

	// Path of the KVv2 mount to use. (Default is "kv".)
	SecretsMountPath string `json:"secrets_mount_path,omitempty"`

	// Path in the KVv2 mount to use. (Default is "caddy".)
	SecretsPathPrefix string `json:"secrets_path_prefix,omitempty"`

	// Limit of connection retries after which to fail a request. (Default is 3.)
	MaxRetries int `json:"max_retries,omitempty"`

	// Timeout for locks (in seconds). (Default is 60.)
	LockTimeout int `json:"lock_timeout,omitempty"`

	// Interval for checking lock status (in seconds). (Default is 5.)
	LockCheckInterval int `json:"lock_check_interval,omitempty"`
	// contains filtered or unexported fields
}

A highly available storage module that integrates with HashiCorp Vault.

func New

func New() *VaultStorage

*

  • Creates a new vault storage module instance with default values

func (VaultStorage) CaddyModule

func (VaultStorage) CaddyModule() caddy.ModuleInfo

func (*VaultStorage) CertMagicStorage

func (s *VaultStorage) CertMagicStorage() (certmagic.Storage, error)

func (*VaultStorage) CheckCapabilities added in v1.1.0

func (s *VaultStorage) CheckCapabilities(ctx context.Context) error

*

  • Checks whether the provided token has enough access rights to perform all
  • operations, that this module requires.

func (*VaultStorage) CheckCapabilitiesOnPath added in v1.1.0

func (s *VaultStorage) CheckCapabilitiesOnPath(ctx context.Context, path string, requiredCapabilities []string) (bool, error)

*

  • Checks if a set of required capabilities are granted on a given api path

func (*VaultStorage) Cleanup added in v1.1.0

func (s *VaultStorage) Cleanup() error

func (*VaultStorage) Connect

func (s *VaultStorage) Connect(ctx context.Context) error

*

  • Establishes a connection to a healthy Vault instance. *
  • `s.client` will always be initialized and reused, if already existing, so there
  • can't be a nil dereference error, when at least calling this once. *
  • If there is more than one address configured, every address will be checked
  • to be a healthy Vault instance and the first healthy instance will be used.

func (*VaultStorage) Delete

func (s *VaultStorage) Delete(ctx context.Context, path string) error

*

func (*VaultStorage) Exists

func (s *VaultStorage) Exists(ctx context.Context, path string) bool

*

func (*VaultStorage) List

func (s *VaultStorage) List(ctx context.Context, path string, recursive bool) ([]string, error)

*

func (*VaultStorage) ListAggregate

func (s *VaultStorage) ListAggregate(ctx context.Context, path string, recursive bool, filePathsAggregator *list.List, keyExistsCheck bool) error

*

  • Internal aggregator for existing keys in a specific path.

func (*VaultStorage) Load

func (s *VaultStorage) Load(ctx context.Context, path string) ([]byte, error)

*

func (*VaultStorage) LoadTokenFromFile added in v1.1.0

func (s *VaultStorage) LoadTokenFromFile() error

*

  • Loads the access token from the configured file path

func (*VaultStorage) Lock

func (s *VaultStorage) Lock(ctx context.Context, path string) error

*

func (*VaultStorage) LockEnsureMetadata

func (s *VaultStorage) LockEnsureMetadata(ctx context.Context, path string) error

*

  • Ensures, that metadata exists for a lock. This only has to be done once,
  • but is idempotent.

func (*VaultStorage) LockStat

func (s *VaultStorage) LockStat(ctx context.Context, path string) (LockInfo, error)

*

  • Retreives information about a specific lock.

func (*VaultStorage) PrefixPath

func (s *VaultStorage) PrefixPath(path string) string

*

  • Adds the secrets path prefix (from configuration) to the path provided.

func (*VaultStorage) Provision

func (s *VaultStorage) Provision(ctx caddy.Context) error

func (*VaultStorage) ReconnectOnError

func (s *VaultStorage) ReconnectOnError(ctx context.Context, err error, clientAddressTried string) (bool, error)

*

  • Checks the provieded error and decides, whether a reconnection is necessary,
  • than performs that reconnection and reports it's decision to the caller.

func (*VaultStorage) Stat

func (s *VaultStorage) Stat(ctx context.Context, path string) (certmagic.KeyInfo, error)

*

func (*VaultStorage) StatCheckDirectory

func (s *VaultStorage) StatCheckDirectory(ctx context.Context, path string) (bool, error)

*

  • Checks whether a directory exits on a given path. Files will report as false.

func (*VaultStorage) Store

func (s *VaultStorage) Store(ctx context.Context, path string, value []byte) error

*

func (*VaultStorage) StoreEnsureMetadata

func (s *VaultStorage) StoreEnsureMetadata(ctx context.Context, path string) error

*

  • Ensures, that metadata exists for a key in the key-value store. This only
  • has to be done once, but is idempotent.

func (*VaultStorage) Unlock

func (s *VaultStorage) Unlock(ctx context.Context, path string) error

*

func (*VaultStorage) Validate added in v1.1.0

func (s *VaultStorage) Validate() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL