Documentation
¶
Overview ¶
Package secret provides encrypted secrets management for bc workspaces.
Index ¶
- Constants
- func Decrypt(key []byte, encoded string) ([]byte, error)
- func DeriveKey(passphrase string, salt []byte) []byte
- func Encrypt(key, plaintext []byte) (string, error)
- func GenerateSalt() ([]byte, error)
- func Passphrase() (string, error)
- type LayeredStore
- func (l *LayeredStore) Close() error
- func (l *LayeredStore) Delete(name string) error
- func (l *LayeredStore) DeleteScoped(scope Scope, name string) error
- func (l *LayeredStore) GetMeta(name string) (*SecretMeta, error)
- func (l *LayeredStore) GetValue(name string) (string, error)
- func (l *LayeredStore) Global() *Store
- func (l *LayeredStore) List() ([]*SecretMeta, error)
- func (l *LayeredStore) ResolveEnv(env map[string]string) map[string]string
- func (l *LayeredStore) Set(name, value, description string) error
- func (l *LayeredStore) SetWithScope(scope Scope, name, value, description string) error
- func (l *LayeredStore) SetWorkspace(name, value, description string) error
- func (l *LayeredStore) Workspace() *Store
- type PostgresStore
- func (p *PostgresStore) Close() error
- func (p *PostgresStore) Delete(name string) error
- func (p *PostgresStore) GetMeta(name string) (*SecretMeta, error)
- func (p *PostgresStore) GetValue(name string) (string, error)
- func (p *PostgresStore) InitKey(passphrase string) error
- func (p *PostgresStore) InitSchema() error
- func (p *PostgresStore) List() ([]*SecretMeta, error)
- func (p *PostgresStore) ResolveEnv(env map[string]string) map[string]string
- func (p *PostgresStore) Set(name, value, description string) error
- type Scope
- type SecretMeta
- type Store
- func (s *Store) Close() error
- func (s *Store) Delete(name string) error
- func (s *Store) GetMeta(name string) (*SecretMeta, error)
- func (s *Store) GetValue(name string) (string, error)
- func (s *Store) List() ([]*SecretMeta, error)
- func (s *Store) ResolveEnv(env map[string]string) map[string]string
- func (s *Store) Set(name, value, description string) error
Constants ¶
const PassphraseEnvVar = "BC_SECRET_PASSPHRASE" //nolint:gosec // not a credential, env var name constant
PassphraseEnvVar is the environment variable for the master passphrase.
Variables ¶
This section is empty.
Functions ¶
func Encrypt ¶
Encrypt encrypts plaintext using AES-256-GCM with the given key. Returns base64-encoded ciphertext with the nonce prepended.
func GenerateSalt ¶
GenerateSalt returns a cryptographically random salt.
func Passphrase ¶
Passphrase returns the passphrase for secret encryption. Priority: BC_SECRET_PASSPHRASE env var > auto-generated key file at ~/.bc/secret-key. The key file is created with 0600 permissions on first use.
Types ¶
type LayeredStore ¶ added in v0.2.0
type LayeredStore struct {
// contains filtered or unexported fields
}
LayeredStore composes a user-global vault with an optional workspace-local Store. Reads check workspace first, falling back to global. Writes default to the global vault; callers can target the workspace layer with the *Workspace methods or SetWithScope.
Each underlying Store keeps its own encryption key (derived from the same passphrase + a per-vault salt) so the two files stay independently decryptable. Callers close a LayeredStore with Close() which closes both underlying Stores; ownership flows through the wrapper.
func NewLayeredStore ¶ added in v0.2.0
func NewLayeredStore(global, workspace *Store) *LayeredStore
NewLayeredStore wraps a global vault and an optional workspace Store. Either argument may be nil, but at least one must be non-nil or every call will error.
func (*LayeredStore) Close ¶ added in v0.2.0
func (l *LayeredStore) Close() error
Close closes both underlying stores, returning the first error.
func (*LayeredStore) Delete ¶ added in v0.2.0
func (l *LayeredStore) Delete(name string) error
Delete removes from whichever layer owns the name, preferring workspace. Returns an error when the secret exists in neither.
func (*LayeredStore) DeleteScoped ¶ added in v0.2.0
func (l *LayeredStore) DeleteScoped(scope Scope, name string) error
DeleteScoped removes from a specific scope. Useful for "bc secret delete NAME --global" / "--workspace".
func (*LayeredStore) GetMeta ¶ added in v0.2.0
func (l *LayeredStore) GetMeta(name string) (*SecretMeta, error)
GetMeta returns the metadata from whichever layer owns the name, with the workspace override winning. The returned meta's Scope field is populated to reflect the owning layer.
func (*LayeredStore) GetValue ¶ added in v0.2.0
func (l *LayeredStore) GetValue(name string) (string, error)
GetValue returns the decrypted value, preferring the workspace scope.
func (*LayeredStore) Global ¶ added in v0.2.0
func (l *LayeredStore) Global() *Store
Global returns the underlying user-global Store (never nil when the LayeredStore was constructed correctly).
func (*LayeredStore) List ¶ added in v0.2.0
func (l *LayeredStore) List() ([]*SecretMeta, error)
List returns metadata for every secret in both layers. When a name exists in both, the workspace entry wins and scope is reported as "workspace".
func (*LayeredStore) ResolveEnv ¶ added in v0.2.0
func (l *LayeredStore) ResolveEnv(env map[string]string) map[string]string
ResolveEnv substitutes ${secret:NAME} in each value. Names are resolved with workspace-over-global precedence.
func (*LayeredStore) Set ¶ added in v0.2.0
func (l *LayeredStore) Set(name, value, description string) error
Set writes to the user-global vault (the default for bc secret add KEY=VAL). Use SetWorkspace for per-workspace overrides.
func (*LayeredStore) SetWithScope ¶ added in v0.2.0
func (l *LayeredStore) SetWithScope(scope Scope, name, value, description string) error
SetWithScope chooses a layer explicitly; empty scope defaults to global when it exists, else workspace.
func (*LayeredStore) SetWorkspace ¶ added in v0.2.0
func (l *LayeredStore) SetWorkspace(name, value, description string) error
SetWorkspace writes to the per-workspace override store.
func (*LayeredStore) Workspace ¶ added in v0.2.0
func (l *LayeredStore) Workspace() *Store
Workspace returns the optional per-workspace override Store.
type PostgresStore ¶
type PostgresStore struct {
// contains filtered or unexported fields
}
PostgresStore provides Postgres-backed encrypted secrets storage.
func NewPostgresStore ¶
func NewPostgresStore(db *sql.DB) *PostgresStore
NewPostgresStore creates a PostgresStore from an existing *sql.DB connection.
func (*PostgresStore) Close ¶
func (p *PostgresStore) Close() error
Close closes the database connection. Close is a no-op — the shared DB is owned by the caller.
func (*PostgresStore) Delete ¶
func (p *PostgresStore) Delete(name string) error
Delete removes a secret.
func (*PostgresStore) GetMeta ¶
func (p *PostgresStore) GetMeta(name string) (*SecretMeta, error)
GetMeta returns metadata for a secret (no value).
func (*PostgresStore) GetValue ¶
func (p *PostgresStore) GetValue(name string) (string, error)
GetValue retrieves and decrypts a secret value.
func (*PostgresStore) InitKey ¶
func (p *PostgresStore) InitKey(passphrase string) error
InitKey derives or loads the encryption key from the passphrase.
func (*PostgresStore) InitSchema ¶
func (p *PostgresStore) InitSchema() error
InitSchema creates the secrets tables in Postgres if they don't exist.
func (*PostgresStore) List ¶
func (p *PostgresStore) List() ([]*SecretMeta, error)
List returns metadata for all secrets (no values).
func (*PostgresStore) ResolveEnv ¶
func (p *PostgresStore) ResolveEnv(env map[string]string) map[string]string
ResolveEnv resolves ${secret:NAME} references in env vars.
func (*PostgresStore) Set ¶
func (p *PostgresStore) Set(name, value, description string) error
Set creates or updates a secret with an encrypted value.
type Scope ¶ added in v0.2.0
type Scope string
Scope distinguishes which layer of a layered secret store holds a value. It is a runtime attribute reported in SecretMeta.Scope.
type SecretMeta ¶
type SecretMeta struct {
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Scope Scope `json:"scope,omitempty"`
}
SecretMeta holds secret metadata (never includes the value).
Scope is runtime-only and reports which layer of a LayeredStore owns the secret ("global" or "workspace"). Plain-store lookups leave it empty.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides encrypted secrets storage backed by SQLite or Postgres. Values are encrypted with AES-256-GCM; the encryption key is derived from a master passphrase via PBKDF2.
func NewStore ¶
NewStore creates a new secrets store for the given workspace path. The passphrase is used to derive the encryption key via PBKDF2.
func OpenStore ¶
OpenStore opens the secrets store using the shared workspace database. Uses the shared driver type to determine the backend (timescale or sqlite). The secret store keeps encryption isolation — its own salt and key derivation.
func OpenVaultFile ¶ added in v0.2.0
OpenVaultFile opens a Store using an explicit SQLite path instead of the conventional "<workspacePath>/.bc/secrets.db". Used for the user-global vault at ~/.bc/secrets.vault where there is no "workspace" to anchor against. Directory must exist.
func (*Store) GetMeta ¶
func (s *Store) GetMeta(name string) (*SecretMeta, error)
GetMeta returns metadata for a secret (no value).
func (*Store) List ¶
func (s *Store) List() ([]*SecretMeta, error)
List returns metadata for all secrets (no values).
func (*Store) ResolveEnv ¶
ResolveEnv resolves ${secret:NAME} references in env vars, returning a new map with secret values substituted. Unresolvable refs are left as-is.