Documentation
¶
Overview ¶
Package config loads locksql profiles from the project and user config files, applies defaults, refuses anything that looks like a secret, and computes the security-relevant policy of a profile.
Index ¶
- Constants
- func ApprovedKey(root, profile string) string
- func DefaultDetectors() []string
- func DefaultPort(engine string) int
- func FindProjectRoot(cwd string) (string, bool)
- func Fingerprint(p Policy) string
- func IsLoopback(host string) bool
- func ParseProfiles(data []byte, name, baseDir string) (map[string]Profile, error)
- func ProjectHash(root string) string
- func ProjectKey(cwd string) string
- func SSHString(s *SSHProfile) string
- func SaveApproved(stateDir, key string, p Policy) error
- func StateDir() (string, error)
- func TLSRank(mode string) int
- func TLSVerifiesChain(mode, ca string) bool
- func UserConfigPath() (string, error)
- type Change
- type Config
- type Limits
- type Policy
- type Profile
- type SSHProfile
- type Tier
Constants ¶
const ( TLSDisable = "disable" TLSPrefer = "prefer" TLSRequire = "require" TLSVerifyCA = "verify-ca" TLSVerifyFull = "verify-full" )
TLS modes of a network profile, as libpq's sslmode, in increasing strength.
const ( SSHAuthKey = "key" SSHAuthAgent = "agent" SSHAuthPassword = "password" )
SSH authentication methods.
const ( EngineMariaDB = "mariadb" EngineMySQL = "mysql" EnginePostgres = "postgres" EngineSQLite = "sqlite" )
Supported engines.
const ( CredentialsAsk = "ask" CredentialsKeychain = "keychain" )
Credentials modes.
const ( MinIdleTimeout = time.Minute MaxMaxSession = 24 * time.Hour )
Bounds of the session limits: MinIdleTimeout <= idle_timeout <= max_session <= MaxMaxSession.
const DefaultMaskMode = "redact"
DefaultMaskMode is the mode of a mask rule that sets none.
const DefaultSSHPort = 22
DefaultSSHPort is the port of an ssh table that leaves port unset.
Variables ¶
This section is empty.
Functions ¶
func ApprovedKey ¶
ApprovedKey names the approved-policy file of a profile: <ProjectHash(root)>-<profile>, or user-<profile> for a profile that comes from the user config only (root == "").
func DefaultDetectors ¶
func DefaultDetectors() []string
DefaultDetectors is the detector set used when a profile does not set detectors. National id detectors are opt-in.
func DefaultPort ¶ added in v0.5.0
DefaultPort is the port of engine when a profile leaves port unset, 0 for an engine without one (sqlite).
func FindProjectRoot ¶
FindProjectRoot walks up from cwd to the first directory holding .locksql/config.toml.
func Fingerprint ¶
Fingerprint returns the hex sha256 of the policy's canonical JSON. List order does not change the fingerprint.
func IsLoopback ¶ added in v0.5.0
IsLoopback reports a host that names this machine: "localhost" or a loopback IP literal. Any other name, even one that resolves to loopback, is remote.
func ParseProfiles ¶ added in v0.1.2
ParseProfiles decodes and validates config data. name labels errors. Relative sqlite paths are resolved against baseDir. Errors never quote config values that could be secrets.
func ProjectHash ¶
ProjectHash returns the first 8 hex digits of sha256 of the absolute, cleaned project root.
func ProjectKey ¶
ProjectKey names the project of cwd in socket paths: ProjectHash of the project root, or "user" when cwd is outside any project (profiles from the user config only). The console and its clients must agree on it.
func SSHString ¶ added in v0.5.0
func SSHString(s *SSHProfile) string
SSHString shows a bastion in a policy change.
func SaveApproved ¶
SaveApproved atomically writes the policy to <stateDir>/locksql/approved/<key>.json with mode 0600.
func StateDir ¶
StateDir returns the user state directory (without the locksql suffix): $XDG_STATE_HOME or ~/.local/state on Linux and other Unix systems, and os.UserConfigDir() on macOS.
func TLSRank ¶ added in v0.5.0
TLSRank orders TLS modes by strength. "" is prefer, the mode of profiles approved before the setting existed; an unknown mode ranks -1.
func TLSVerifiesChain ¶ added in v0.5.0
TLSVerifiesChain reports a tls mode that verifies the server's certificate chain: verify-ca and verify-full, and require with tls_ca, as libpq.
func UserConfigPath ¶ added in v0.1.2
UserConfigPath returns <user config dir>/locksql/config.toml.
Types ¶
type Change ¶
Change is one difference between two policies. For list fields (detectors, pii.mask, pii.allow) each added or removed element is its own Change, with Old empty for an addition and New empty for a removal.
func Diff ¶
Diff lists the changes from approved to current and marks each loosening (spec section 4): a higher tier, production true→false, a larger limit (0 means unlimited), a longer idle_timeout or max_session, a removed PII rule or detector, an added allow rule, any change of engine, host, port, path, database or user, and a credentials mode other than ask, a weaker tls mode, any change of tls_ca, tls_cert, tls_key or tls_server_name and any change of the ssh table.
type Config ¶
type Config struct {
// ProjectRoot is the directory holding .locksql/config.toml, or "" when
// no project config was found.
ProjectRoot string
Profiles map[string]Profile
}
Config is the merged set of profiles visible from a working directory.
type Limits ¶
type Limits struct {
StatementTimeout time.Duration `toml:"statement_timeout" json:"statement_timeout"`
ExplainRowsWarn int64 `toml:"explain_rows_warn" json:"explain_rows_warn"`
ExplainRowsRefuse int64 `toml:"explain_rows_refuse" json:"explain_rows_refuse"`
MaxRows int `toml:"max_rows" json:"max_rows"`
MaxCellChars int `toml:"max_cell_chars" json:"max_cell_chars"`
MaxOutputBytes int `toml:"max_output_bytes" json:"max_output_bytes"`
// ExplainCostRefuse refuses a plan whose total cost, in the engine's
// own units, is above it; 0 disables the check. Engines without a cost
// (SQLite) are not checked.
ExplainCostRefuse float64 `toml:"explain_cost_refuse" json:"explain_cost_refuse,omitempty"`
// KAnonymity is the smallest number of rows a PII filter, a grouping
// on a PII column or an aggregate of one may cover.
KAnonymity int `toml:"k_anonymity" json:"k_anonymity,omitempty"`
// ReferenceProbe is how many distinct cells of one result the agent may
// filter on, one statement each, before the console warns of equality
// probing; raising it is a loosening.
ReferenceProbe int `toml:"reference_probe" json:"reference_probe,omitempty"`
// IdleTimeout ends the console session after that long without
// activity, MaxSession after that long in all; raising either is a
// loosening. Bounds: 1m <= IdleTimeout <= MaxSession <= 24h.
IdleTimeout time.Duration `toml:"idle_timeout" json:"idle_timeout,omitempty"`
MaxSession time.Duration `toml:"max_session" json:"max_session,omitempty"`
}
Limits bound the cost and size of one statement.
func DefaultLimits ¶
DefaultLimits returns the limits applied to unset (zero) limit fields.
type Policy ¶
type Policy struct {
Profile Profile `json:"profile"`
PIIMask []string `json:"pii_mask"` // sorted column patterns
PIIAllow []string `json:"pii_allow"` // sorted column patterns
// PIIModes maps a mask pattern to its mode when it is not the default
// (redact): partial or email.
PIIModes map[string]string `json:"pii_modes,omitempty"`
}
Policy is the security-relevant view of one profile plus its PII rules. The console compares the current policy with the last approved one and asks the human before applying any loosening.
func LoadApproved ¶
LoadApproved reads <stateDir>/locksql/approved/<key>.json. When no policy was approved yet, the error wraps fs.ErrNotExist.
type Profile ¶
type Profile struct {
Name string `json:"name"`
Engine string `json:"engine"`
Host string `json:"host"`
Path string `json:"path"`
User string `json:"user"`
Database string `json:"database"`
Credentials string `json:"credentials"`
// TLS is the transport mode (TLSDisable ... TLSVerifyFull) and TLSCA an
// optional PEM bundle that replaces the system roots.
TLS string `json:"tls,omitempty"`
TLSCA string `json:"tls_ca,omitempty"`
// TLSCert and TLSKey are the PEM files of a client certificate and its
// private key, presented when the server asks for one. TLSServerName
// replaces host as the name verify-full checks in the certificate.
TLSCert string `json:"tls_cert,omitempty"`
TLSKey string `json:"tls_key,omitempty"`
TLSServerName string `json:"tls_server_name,omitempty"`
// SSH, when set, is the bastion the profile is reached through.
SSH *SSHProfile `json:"ssh,omitempty"`
Port int `json:"port"`
Tier Tier `json:"tier"`
Production bool `json:"production"`
Detectors []string `json:"detectors"`
Limits Limits `json:"limits"`
// CredentialsTTL makes the console ask for the secret again (and
// reconnect) once the connection is that old; 0 keeps it for the
// session. It suits short-lived secrets from a vault.
CredentialsTTL time.Duration `json:"credentials_ttl,omitempty"`
}
Profile is one named database target with its policy. It never holds a secret.
type SSHProfile ¶ added in v0.5.0
type SSHProfile struct {
Host string `json:"host"`
Port int `json:"port"`
User string `json:"user"`
Auth string `json:"auth"`
Key string `json:"key,omitempty"`
Credentials string `json:"credentials"`
}
SSHProfile is the bastion a network profile is reached through. Host and Port of the profile are then seen from the bastion. It never holds a secret: a key passphrase or an SSH password follows Credentials.
type Tier ¶
type Tier int
Tier is the highest statement class a profile may run. The order is TierRead < TierWrite < TierDDL < TierAdmin.
func (Tier) MarshalText ¶
MarshalText encodes the tier by name.
func (*Tier) UnmarshalText ¶
UnmarshalText decodes a tier name.