secrets

package
v0.0.0-...-51f9457 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2021 License: Apache-2.0 Imports: 27 Imported by: 0

Documentation

Overview

Package secrets provides a secrets store based on Google Secret Manager.

It supports stored and auto-generated secrets.

Stored secrets are predefined blobs or texts (e.g. passwords) that are placed in the Google Secret Manager and then read back via this package. How secrets are written is outside the scope of this package, it just reads them.

Auto-generated secrets are random high-entropy strings with no inherent structure. They are usually derived via a key derivation function from their name and some root secret read from Google Secret Manager. They are useful when calculating HMACs, as salts, etc.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoSuchSecret indicates the store can't find the requested secret.
	ErrNoSuchSecret = errors.New("secret not found")
	// ErrNoStoreConfigured indicates there's no Store in the context.
	ErrNoStoreConfigured = errors.New("secrets.Store is not in the context")
)
View Source
var ModuleName = module.RegisterName("go.chromium.org/luci/server/secrets")

ModuleName can be used to refer to this module when declaring dependencies.

Functions

func AddRotationHandler

func AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error

AddRotationHandler registers a callback called when the secret is updated.

If the context doesn't have Store set, returns ErrNoStoreConfigured.

func NewModule

func NewModule(opts *ModuleOptions) module.Module

NewModule returns a server module that adds a secret store backed by Google Secret Manager to the global server context.

func NewModuleFromFlags

func NewModuleFromFlags() module.Module

NewModuleFromFlags is a variant of NewModule that initializes options through command line flags.

Calling this function registers flags in flag.CommandLine. They are usually parsed in server.Main(...).

func Use

func Use(ctx context.Context, s Store) context.Context

Use installs a Store implementation into the context.

Types

type DerivedStore

type DerivedStore struct {
	// contains filtered or unexported fields
}

DerivedStore implements Store by deriving secrets from some single root secret using HKDF.

Caches all derived secrets internally forever. Assumes the set of possible key names is limited.

func NewDerivedStore

func NewDerivedStore(root Secret) *DerivedStore

NewDerivedStore returns a store that derives secrets from the given root key.

func (*DerivedStore) AddRotationHandler

func (d *DerivedStore) AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error

AddRotationHandler is not implemented.

func (*DerivedStore) RandomSecret

func (d *DerivedStore) RandomSecret(ctx context.Context, name string) (Secret, error)

RandomSecret returns a generated secret given its name.

func (*DerivedStore) SetRoot

func (d *DerivedStore) SetRoot(root Secret)

SetRoot replaces the root key used to derive secrets.

func (*DerivedStore) StoredSecret

func (d *DerivedStore) StoredSecret(ctx context.Context, name string) (Secret, error)

StoredSecret returns an error, since DerivedStore always derives secrets.

type ModuleOptions

type ModuleOptions struct {
	// RootSecret points to the root secret used to derive random secrets.
	//
	// In production it should be a reference to a Google Secret Manager secret
	// (in a form "sm://<project>/<secret>" or just "sm://<secret>" to fetch it
	// from the current project).
	//
	// In non-production environments it can be a literal secret value in a form
	// "devsecret://<base64-encoded secret>" or "devsecret-text://<secret>". If
	// omitted in a non-production environment, some phony hardcoded value is
	// used.
	//
	// When using Google Secret Manager, the secret version "latest" is used to
	// get the current value of the root secret, and a single immediately
	// preceding previous version (if it is still enabled) is used to get the
	// previous version of the root secret. This allows graceful rotation of
	// random secrets.
	RootSecret string
}

ModuleOptions contain configuration of the secrets server module.

func (*ModuleOptions) Register

func (o *ModuleOptions) Register(f *flag.FlagSet)

Register registers the command line flags.

type RotationHandler

type RotationHandler func(context.Context, Secret)

RotationHandler is called from an internal goroutine after the store fetches a new version of a stored secret.

type Secret

type Secret struct {
	Current  []byte   `json:"current"`            // current value of the secret, always set
	Previous [][]byte `json:"previous,omitempty"` // optional list of previous values, most recent first
}

Secret represents a current value of a secret as well as a set of few previous values. Previous values are important when the secret is being rotated: there may be valid outstanding derivatives of previous values of the secret.

func RandomSecret

func RandomSecret(ctx context.Context, name string) (Secret, error)

RandomSecret returns a random secret using Store in the context.

If the context doesn't have Store set, returns ErrNoStoreConfigured.

func StoredSecret

func StoredSecret(ctx context.Context, name string) (Secret, error)

StoredSecret returns a stored secret using Store in the context.

If the context doesn't have Store set, returns ErrNoStoreConfigured.

func (Secret) Blobs

func (s Secret) Blobs() [][]byte

Blobs returns current blob and all previous blobs as one array.

func (Secret) Equal

func (s Secret) Equal(a Secret) bool

Equal returns true if secrets are equal.

Does *not* run in constant time. Shouldn't be used in a cryptographic context due to susceptibility to timing attacks.

type SecretManagerStore

type SecretManagerStore struct {
	// CloudProject is used for loading secrets of the form "sm://<name>".
	CloudProject string
	// AccessSecretVersion is an RPC to fetch the secret from the Secret Manager.
	AccessSecretVersion func(context.Context, *secretmanagerpb.AccessSecretVersionRequest, ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error)
	// contains filtered or unexported fields
}

SecretManagerStore implements Store using Google Secret Manager.

Stored secrets are fetched directly from Google Secret Manager. Random secrets are derived from a root secret using HKDF via DerivedStore.

func (*SecretManagerStore) AddRotationHandler

func (sm *SecretManagerStore) AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error

AddRotationHandler registers a callback which is called when the stored secret is updated.

The handler is called from an internal goroutine and receives a context passed to MaintenanceLoop. If multiple handlers for the same secret are registered, they are called in order of their registration one by one.

func (*SecretManagerStore) LoadRootSecret

func (sm *SecretManagerStore) LoadRootSecret(ctx context.Context, rootSecret string) error

LoadRootSecret loads the root secret used to generate random secrets.

See StoredSecret for the format of the root secret.

func (*SecretManagerStore) MaintenanceLoop

func (sm *SecretManagerStore) MaintenanceLoop(ctx context.Context)

MaintenanceLoop runs a loop that periodically rereads secrets.

It exits on context cancellation. Logs errors inside.

func (*SecretManagerStore) RandomSecret

func (sm *SecretManagerStore) RandomSecret(ctx context.Context, name string) (Secret, error)

RandomSecret returns a random secret given its name.

func (*SecretManagerStore) SetRandomSecretsStore

func (sm *SecretManagerStore) SetRandomSecretsStore(s Store)

SetRandomSecretsStore changes the store used for RandomSecret(...).

Can be used instead of LoadRootSecret to hook up a custom implementation.

func (*SecretManagerStore) StoredSecret

func (sm *SecretManagerStore) StoredSecret(ctx context.Context, name string) (Secret, error)

StoredSecret returns a previously stored secret given its name.

Value of `name` should have form:

  • `sm://<project>/<secret>`: a concrete secret in Google Secret Manager.
  • `sm://<secret>`: same as `sm://<CloudProject>/<secret>`.
  • `devsecret://<base64-encoded secret>`: return this concrete secret.
  • `devsecret-text://<string>`: return this concrete secret.

type Store

type Store interface {
	// RandomSecret returns a random secret given its name.
	//
	// The store will auto-generate the secret if necessary. Its value is
	// a random high-entropy blob.
	RandomSecret(ctx context.Context, name string) (Secret, error)

	// StoredSecret returns a previously stored secret given its name.
	//
	// How it was stored depends on the concrete implementation of the Store. The
	// difference from RandomSecret is that the Store will never try to
	// auto-generate such secret if it is missing and will return ErrNoSuchSecret
	// instead.
	StoredSecret(ctx context.Context, name string) (Secret, error)

	// AddRotationHandler registers a callback called when the secret is updated.
	//
	// Useful when a value of StoredSecret(...) is used to derive something else.
	// The callback allows the store to notify the consumer of the secret when
	// it changes.
	AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error
}

Store knows how to retrieve or autogenerate a secret given its name.

See SecretManagerStore for a concrete implementation usually used in production.

func CurrentStore

func CurrentStore(ctx context.Context) Store

CurrentStore returns a store installed in the context or nil.

Directories

Path Synopsis
Package testsecrets provides a dumb in-memory secret store to use in unit tests.
Package testsecrets provides a dumb in-memory secret store to use in unit tests.

Jump to

Keyboard shortcuts

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