influxdb/bolt/secret.go

255 lines
5.6 KiB
Go
Raw Normal View History

package bolt
import (
"context"
"encoding/base64"
"errors"
"fmt"
bolt "github.com/coreos/bbolt"
influxdb "github.com/influxdata/influxdb"
)
var (
secretBucket = []byte("secretsv1")
)
var _ influxdb.SecretService = (*Client)(nil)
func (c *Client) initializeSecretService(ctx context.Context, tx *bolt.Tx) error {
if _, err := tx.CreateBucketIfNotExists([]byte(secretBucket)); err != nil {
return err
}
return nil
}
// LoadSecret retrieves the secret value v found at key k for organization orgID.
func (c *Client) LoadSecret(ctx context.Context, orgID influxdb.ID, k string) (string, error) {
var v string
err := c.db.View(func(tx *bolt.Tx) error {
val, err := c.loadSecret(ctx, tx, orgID, k)
if err != nil {
return err
}
v = val
return nil
})
if err != nil {
return "", err
}
return v, nil
}
func (c *Client) loadSecret(ctx context.Context, tx *bolt.Tx, orgID influxdb.ID, k string) (string, error) {
key, err := encodeSecretKey(orgID, k)
if err != nil {
return "", err
}
val := tx.Bucket(secretBucket).Get(key)
if len(val) == 0 {
return "", &influxdb.Error{
Code: influxdb.ENotFound,
Msg: influxdb.ErrSecretNotFound,
}
}
v, err := decodeSecretValue(val)
if err != nil {
return "", err
}
return v, nil
}
// GetSecretKeys retrieves all secret keys that are stored for the organization orgID.
func (c *Client) GetSecretKeys(ctx context.Context, orgID influxdb.ID) ([]string, error) {
var vs []string
err := c.db.View(func(tx *bolt.Tx) error {
vals, err := c.getSecretKeys(ctx, tx, orgID)
if err != nil {
return err
}
vs = vals
return nil
})
if err != nil {
return nil, err
}
return vs, nil
}
func (c *Client) getSecretKeys(ctx context.Context, tx *bolt.Tx, orgID influxdb.ID) ([]string, error) {
cur := tx.Bucket(secretBucket).Cursor()
prefix, err := orgID.Encode()
if err != nil {
return nil, err
}
k, _ := cur.Seek(prefix)
if len(k) == 0 {
return []string{}, nil
}
id, key, err := decodeSecretKey(k)
if err != nil {
return nil, err
}
if id != orgID {
return nil, fmt.Errorf("organization has no secret keys")
}
keys := []string{key}
for {
k, _ = cur.Next()
if len(k) == 0 {
// We've reached the end of the keys so we're done
break
}
id, key, err = decodeSecretKey(k)
if err != nil {
return nil, err
}
if id != orgID {
// We've reached the end of the keyspace for the provided orgID
break
}
keys = append(keys, key)
}
return keys, nil
}
// PutSecret stores the secret pair (k,v) for the organization orgID.
func (c *Client) PutSecret(ctx context.Context, orgID influxdb.ID, k, v string) error {
return c.db.Update(func(tx *bolt.Tx) error {
return c.putSecret(ctx, tx, orgID, k, v)
})
}
func (c *Client) putSecret(ctx context.Context, tx *bolt.Tx, orgID influxdb.ID, k, v string) error {
key, err := encodeSecretKey(orgID, k)
if err != nil {
return err
}
val := encodeSecretValue(v)
if err := tx.Bucket(secretBucket).Put(key, val); err != nil {
return err
}
return nil
}
func encodeSecretKey(orgID influxdb.ID, k string) ([]byte, error) {
buf, err := orgID.Encode()
if err != nil {
return nil, err
}
key := make([]byte, 0, influxdb.IDLength+len(k))
key = append(key, buf...)
key = append(key, k...)
return key, nil
}
func decodeSecretKey(key []byte) (influxdb.ID, string, error) {
if len(key) < influxdb.IDLength {
// This should not happen.
return influxdb.InvalidID(), "", errors.New("provided key is too short to contain an ID (please report this error)")
}
var id influxdb.ID
if err := id.Decode(key[:influxdb.IDLength]); err != nil {
return influxdb.InvalidID(), "", err
}
k := string(key[influxdb.IDLength:])
return id, k, nil
}
func decodeSecretValue(val []byte) (string, error) {
// store the secret value base64 encoded so that it's marginally better than plaintext
v := make([]byte, base64.StdEncoding.DecodedLen(len(val)))
if _, err := base64.StdEncoding.Decode(v, val); err != nil {
return "", err
}
return string(v), nil
}
func encodeSecretValue(v string) []byte {
val := make([]byte, base64.StdEncoding.EncodedLen(len(v)))
base64.StdEncoding.Encode(val, []byte(v))
return val
}
feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): remove explicit logrus dependency chore(platform): run go mod tidy chore(platform): replace github.com/Sirupsen/logrus with github.com/sirupsen/logrus chore(platform): update docker dependency feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): run go mod tidy feat(vault): add vault implementation of secret service chore(platform): make go modules tidy feat(platform): add Put/Patch/Delete methods on secret service feat(vault): add Put/Patch/Delete methods on vault secret service feat(http): add http handler methods for secret service feat(bolt): add Put/Delete/Patch methods to bolt secret service feat(testing): add tests for Put/Patch/Delete methods in secret service feat(mock): add mock secret service feat(http): add tests for secrets endpoints feat(http): update swagger for secrets endpoints chore: run go mod tidy
2018-11-16 16:45:00 +00:00
// PutSecrets puts all provided secrets and overwrites any previous values.
func (c *Client) PutSecrets(ctx context.Context, orgID influxdb.ID, m map[string]string) error {
feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): remove explicit logrus dependency chore(platform): run go mod tidy chore(platform): replace github.com/Sirupsen/logrus with github.com/sirupsen/logrus chore(platform): update docker dependency feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): run go mod tidy feat(vault): add vault implementation of secret service chore(platform): make go modules tidy feat(platform): add Put/Patch/Delete methods on secret service feat(vault): add Put/Patch/Delete methods on vault secret service feat(http): add http handler methods for secret service feat(bolt): add Put/Delete/Patch methods to bolt secret service feat(testing): add tests for Put/Patch/Delete methods in secret service feat(mock): add mock secret service feat(http): add tests for secrets endpoints feat(http): update swagger for secrets endpoints chore: run go mod tidy
2018-11-16 16:45:00 +00:00
return c.db.Update(func(tx *bolt.Tx) error {
keys, err := c.getSecretKeys(ctx, tx, orgID)
if err != nil {
return err
}
for k, v := range m {
if err := c.putSecret(ctx, tx, orgID, k, v); err != nil {
return err
}
}
for _, k := range keys {
if _, ok := m[k]; !ok {
if err := c.deleteSecret(ctx, tx, orgID, k); err != nil {
return err
}
}
}
return nil
})
}
// PatchSecrets patches all provided secrets and updates any previous values.
func (c *Client) PatchSecrets(ctx context.Context, orgID influxdb.ID, m map[string]string) error {
feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): remove explicit logrus dependency chore(platform): run go mod tidy chore(platform): replace github.com/Sirupsen/logrus with github.com/sirupsen/logrus chore(platform): update docker dependency feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): run go mod tidy feat(vault): add vault implementation of secret service chore(platform): make go modules tidy feat(platform): add Put/Patch/Delete methods on secret service feat(vault): add Put/Patch/Delete methods on vault secret service feat(http): add http handler methods for secret service feat(bolt): add Put/Delete/Patch methods to bolt secret service feat(testing): add tests for Put/Patch/Delete methods in secret service feat(mock): add mock secret service feat(http): add tests for secrets endpoints feat(http): update swagger for secrets endpoints chore: run go mod tidy
2018-11-16 16:45:00 +00:00
return c.db.Update(func(tx *bolt.Tx) error {
for k, v := range m {
if err := c.putSecret(ctx, tx, orgID, k, v); err != nil {
return err
}
}
return nil
})
}
// DeleteSecret removes secrets from the secret store.
func (c *Client) DeleteSecret(ctx context.Context, orgID influxdb.ID, ks ...string) error {
feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): remove explicit logrus dependency chore(platform): run go mod tidy chore(platform): replace github.com/Sirupsen/logrus with github.com/sirupsen/logrus chore(platform): update docker dependency feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): run go mod tidy feat(vault): add vault implementation of secret service chore(platform): make go modules tidy feat(platform): add Put/Patch/Delete methods on secret service feat(vault): add Put/Patch/Delete methods on vault secret service feat(http): add http handler methods for secret service feat(bolt): add Put/Delete/Patch methods to bolt secret service feat(testing): add tests for Put/Patch/Delete methods in secret service feat(mock): add mock secret service feat(http): add tests for secrets endpoints feat(http): update swagger for secrets endpoints chore: run go mod tidy
2018-11-16 16:45:00 +00:00
return c.db.Update(func(tx *bolt.Tx) error {
for _, k := range ks {
if err := c.deleteSecret(ctx, tx, orgID, k); err != nil {
return err
}
}
return nil
})
}
func (c *Client) deleteSecret(ctx context.Context, tx *bolt.Tx, orgID influxdb.ID, k string) error {
feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): remove explicit logrus dependency chore(platform): run go mod tidy chore(platform): replace github.com/Sirupsen/logrus with github.com/sirupsen/logrus chore(platform): update docker dependency feat(vault): add vault implementation of secret service test(platform): run testcontainer integration tests for nightly release Integration tests for the vault secret service using testcontiners should not run along with unit tests, however, they should run on some regular schedule. This commit introduces `make test-integration` which runs integration tests for vault using testcontainers. The command introduced relies on docker being available on the host it is executed on. chore(platform): make go modules tidy chore: try to fix go mod chore(platform): run go mod tidy feat(vault): add vault implementation of secret service chore(platform): make go modules tidy feat(platform): add Put/Patch/Delete methods on secret service feat(vault): add Put/Patch/Delete methods on vault secret service feat(http): add http handler methods for secret service feat(bolt): add Put/Delete/Patch methods to bolt secret service feat(testing): add tests for Put/Patch/Delete methods in secret service feat(mock): add mock secret service feat(http): add tests for secrets endpoints feat(http): update swagger for secrets endpoints chore: run go mod tidy
2018-11-16 16:45:00 +00:00
key, err := encodeSecretKey(orgID, k)
if err != nil {
return err
}
return tx.Bucket(secretBucket).Delete(key)
}