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 ¶
- Variables
- func AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error
- func NewModule(opts *ModuleOptions) module.Module
- func NewModuleFromFlags() module.Module
- func Use(ctx context.Context, s Store) context.Context
- type DerivedStore
- func (d *DerivedStore) AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error
- func (d *DerivedStore) RandomSecret(ctx context.Context, name string) (Secret, error)
- func (d *DerivedStore) SetRoot(root Secret)
- func (d *DerivedStore) StoredSecret(ctx context.Context, name string) (Secret, error)
- type ModuleOptions
- type RotationHandler
- type Secret
- type SecretManagerStore
- func (sm *SecretManagerStore) AddRotationHandler(ctx context.Context, name string, cb RotationHandler) error
- func (sm *SecretManagerStore) LoadRootSecret(ctx context.Context, rootSecret string) error
- func (sm *SecretManagerStore) MaintenanceLoop(ctx context.Context)
- func (sm *SecretManagerStore) RandomSecret(ctx context.Context, name string) (Secret, error)
- func (sm *SecretManagerStore) SetRandomSecretsStore(s Store)
- func (sm *SecretManagerStore) StoredSecret(ctx context.Context, name string) (Secret, error)
- type Store
Constants ¶
This section is empty.
Variables ¶
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") )
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 ¶
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(...).
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 ¶
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 ¶
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 ¶
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 ¶
RandomSecret returns a random secret using Store in the context.
If the context doesn't have Store set, returns ErrNoStoreConfigured.
func StoredSecret ¶
StoredSecret returns a stored secret using Store in the context.
If the context doesn't have Store set, returns ErrNoStoreConfigured.
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 ¶
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 ¶
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 ¶
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. |