1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
package vault
import (
"errors"
"fmt"
"github.com/hashicorp/vault/api"
)
type Client interface {
Authenticate(auth AuthMethod) error
Write(path string, data map[string]interface{}) (Result, error)
Read(path string) (Result, error)
Delete(path string) error
}
type defaultClient struct {
internal apiClient
}
type apiClient interface {
Sys() apiClientSys
Logical() apiClientLogical
SetToken(v string)
SetNamespace(ns string)
}
type apiClientSys interface {
Health() (*api.HealthResponse, error)
}
type apiClientLogical interface {
Write(path string, data map[string]interface{}) (*api.Secret, error)
Read(path string) (*api.Secret, error)
Delete(path string) (*api.Secret, error)
}
type apiClientAdapter struct {
c *api.Client
}
func (c *apiClientAdapter) Sys() apiClientSys {
return c.c.Sys()
}
func (c *apiClientAdapter) Logical() apiClientLogical {
return c.c.Logical()
}
func (c *apiClientAdapter) SetToken(v string) {
c.c.SetToken(v)
}
func (c *apiClientAdapter) SetNamespace(ns string) {
c.c.SetNamespace(ns)
}
var (
ErrVaultServerNotReady = errors.New("not initialized or sealed Vault server")
newAPIClient = func(config *api.Config) (apiClient, error) {
c, err := api.NewClient(config)
if err != nil {
return nil, err
}
return &apiClientAdapter{c: c}, nil
}
)
func NewClient(URL string, namespace string) (Client, error) {
config := &api.Config{
Address: URL,
}
client, err := newAPIClient(config)
if err != nil {
return nil, fmt.Errorf("creating new Vault client: %w", unwrapAPIResponseError(err))
}
healthResp, err := client.Sys().Health()
if err != nil {
return nil, fmt.Errorf("checking Vault server health: %w", unwrapAPIResponseError(err))
}
if !healthResp.Initialized || healthResp.Sealed {
return nil, ErrVaultServerNotReady
}
client.SetNamespace(namespace)
c := &defaultClient{
internal: client,
}
return c, nil
}
func (c *defaultClient) Authenticate(auth AuthMethod) error {
err := auth.Authenticate(c)
if err != nil {
return fmt.Errorf("authenticating Vault client: %w", err)
}
c.internal.SetToken(auth.Token())
return nil
}
func (c *defaultClient) Write(path string, data map[string]interface{}) (Result, error) {
secret, err := c.internal.Logical().Write(path, data)
return newResult(secret), unwrapAPIResponseError(err)
}
func (c *defaultClient) Read(path string) (Result, error) {
secret, err := c.internal.Logical().Read(path)
return newResult(secret), unwrapAPIResponseError(err)
}
func (c *defaultClient) Delete(path string) error {
_, err := c.internal.Logical().Delete(path)
return unwrapAPIResponseError(err)
}
|