secrets

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

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

View Source
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.

View Source
const Redacted = "***"

Redacted replaces every occurrence of a secret in a sanitised string.

View Source
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

View Source
var (
	// ErrNotFound means the keychain has no item for the profile and host.
	ErrNotFound = errors.New("secrets: no keychain item")
	// ErrUnavailable means the OS keychain could not be used, for example a
	// headless Linux without a Secret Service. The console then behaves as
	// credentials = "ask".
	ErrUnavailable = errors.New("secrets: OS keychain unavailable")
)
View Source
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.

View Source
var ErrInterrupted = errors.New("secrets: password prompt interrupted")

ErrInterrupted means the human pressed Ctrl-C at the prompt.

View Source
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

func CheckVaultPath(path string) error

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

func KeychainAccount(profile, host string, port int) string

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

func KeychainDelete(profile, host string, port int) error

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

func KeychainHas(profile, host string, port int) error

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

func KeychainSet(profile, host string, port int, s []byte) error

KeychainSet stores s as the secret of profile at host and port, replacing any previous one.

func PromptPassword

func PromptPassword(prompt string) ([]byte, error)

PromptPassword prints prompt on the controlling terminal and reads a line with echo off. Ctrl-C restores the terminal and returns ErrInterrupted.

func Sanitize

func Sanitize(err error, secrets ...[]byte) string

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

func SanitizeString(s string, secrets ...[]byte) string

SanitizeString is Sanitize for a plain string.

func Wipe

func Wipe(b []byte)

Wipe overwrites b with zeros. Go may have copied the bytes elsewhere (string conversions, driver buffers), so this narrows the exposure, it does not end it.

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.

Jump to

Keyboard shortcuts

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