Documentation
¶
Overview ¶
Package secrets reads database secrets from the human (no-echo prompt) or the OS keychain, and scrubs them from error strings. A secret is a []byte that lives only in console memory; callers Wipe it when done.
Index ¶
- Constants
- Variables
- func CheckVaultPath(path string) error
- func KeychainAccount(profile, host string, port int) string
- func KeychainDelete(profile, host string, port int) error
- func KeychainHas(profile, host string, port int) error
- func KeychainSet(profile, host string, port int, s []byte) error
- func PromptPassword(prompt string) ([]byte, error)
- func Sanitize(err error, secrets ...[]byte) string
- func SanitizeString(s string, secrets ...[]byte) string
- func Wipe(b []byte)
- type Legacy
- type VaultCredentials
Constants ¶
const KeychainService = "locksql"
KeychainService is the service name of every locksql keychain item. The account is "<profile>@<host>:<port>", or "<profile>@<path>" for a Unix socket.
const Redacted = "***"
Redacted replaces every occurrence of a secret in a sanitised string.
const VaultCommand = "vault"
VaultCommand is the program run to read a secret from HashiCorp Vault. It inherits the console's environment (VAULT_ADDR, VAULT_TOKEN, VAULT_NAMESPACE, VAULT_CACERT, ...) and its token helper (~/.vault-token): locksql never handles the Vault token itself.
Variables ¶
var ( // ErrNotFound means the keychain has no item for the profile and host. ErrNotFound = errors.New("secrets: no keychain item") // headless Linux without a Secret Service. The console then behaves as // credentials = "ask". ErrUnavailable = errors.New("secrets: OS keychain unavailable") )
var ( // ErrVaultMissing means the vault CLI is not in the console's PATH. ErrVaultMissing = errors.New("secrets: vault CLI not found") // ErrVaultAuth means Vault refused the request: no token, an expired // or revoked one, or a token whose policy may not read the path. ErrVaultAuth = errors.New("secrets: vault: not authenticated or not allowed") // ErrVaultPath means nothing answers at the path: no secret there, or // no secrets engine mounted at its prefix. ErrVaultPath = errors.New("secrets: vault: invalid path") // ErrVaultRole means the secrets engine has no such role. ErrVaultRole = errors.New("secrets: vault: invalid role") // ErrVaultUnreachable means the CLI could not reach the Vault server. ErrVaultUnreachable = errors.New("secrets: vault: server unreachable") // ErrVaultFormat means the secret has no usable password field. ErrVaultFormat = errors.New("secrets: vault: unexpected secret format") // ErrVaultFailed is any other failure of the CLI. ErrVaultFailed = errors.New("secrets: vault read failed") )
Errors of VaultRead. Each is wrapped with a message that says what to do; none carries a value read from Vault.
var ErrInterrupted = errors.New("secrets: password prompt interrupted")
ErrInterrupted means the human pressed Ctrl-C at the prompt.
var ErrNoTerminal = errors.New("secrets: no terminal to prompt for the password")
ErrNoTerminal means there is no controlling terminal to prompt on.
Functions ¶
func CheckVaultPath ¶ added in v0.7.0
CheckVaultPath refuses a path the CLI could misread: empty, starting with "-" or "/", or holding a space or a control character.
func KeychainAccount ¶ added in v0.5.0
KeychainAccount names the keychain item of profile at host and port: "<profile>@<host>:<port>". A Unix-socket host (a path) has no port and keeps "<profile>@<path>". The port is part of the name so that a changed port does not send the stored secret to whatever listens there.
func KeychainDelete ¶
KeychainDelete removes the item of profile at host and port and the legacy "<profile>@<host>" one. ErrNotFound means neither was there.
func KeychainHas ¶ added in v0.5.0
KeychainHas reports whether the keychain holds a secret for profile at host and port, under its name or the legacy one, without moving it: nil when one is there, ErrNotFound when neither is.
func KeychainSet ¶
KeychainSet stores s as the secret of profile at host and port, replacing any previous one.
func PromptPassword ¶
PromptPassword prints prompt on the controlling terminal and reads a line with echo off. Ctrl-C restores the terminal and returns ErrInterrupted.
func Sanitize ¶
Sanitize returns err's message with every secret removed. Besides the raw value it removes the forms a driver might print: URL query, path and userinfo escaping, and Go/JSON string quoting. A nil err gives "".
func SanitizeString ¶
SanitizeString is Sanitize for a plain string.
Types ¶
type Legacy ¶ added in v0.5.0
type Legacy int
Legacy says what KeychainGet did with a pre-upgrade item, named "<profile>@<host>" without the port.
const ( // LegacyNone: no pre-upgrade item was involved. LegacyNone Legacy = iota // LegacyMoved: the item was moved to the name of the default port, and // its secret returned. LegacyMoved // LegacyRemoved: the profile is on another port; the item was deleted // unread and ErrNotFound returned. LegacyRemoved )
func KeychainGet ¶
func KeychainGet(profile, host string, port, defaultPort int) (secret []byte, legacy Legacy, err error)
KeychainGet reads the secret of profile at host and port from the OS keychain. When the item is missing and a pre-upgrade item named "<profile>@<host>" exists, the caller tells the human what happened to it (legacy): on the default port it is moved to the new name once and its secret returned; on any other port it is deleted without being read. The legacy name says nothing of the port, so a changed port must not get the secret, and an item left behind would reach whatever listens on the default port later.
type VaultCredentials ¶ added in v0.7.0
type VaultCredentials struct {
// User is the secret's username field, "" when it has none (a KV secret
// holding the password only).
User string
Password []byte
// LeaseID and LeaseDuration describe a dynamic secret (the database
// secrets engine): the login stops working once the lease ends. A
// static KV secret has no lease ID.
LeaseID string
LeaseDuration time.Duration
}
VaultCredentials is a database login read from Vault. Password lives in memory only; the caller wipes it when done.
func VaultRead ¶ added in v0.7.0
func VaultRead(ctx context.Context, path string) (*VaultCredentials, error)
VaultRead reads the login at path with `vault read -format=json`: the fields username and password of the secret's data, or of data.data for a KV version 2 secret. Every call reads Vault again; nothing is cached or written to disk.