Documentation
¶
Overview ¶
Package cek opens a namespace's SQLite database encrypted at rest.
There is one way to do it:
cek.SetMaster(k) // once, at boot, from KMS db, err := cek.Open(ns, "treasury", dir) // everywhere else
The key is derived from the master and the namespace. It is not generated, not wrapped, not stored, and not rotated in place — so there is no unwrap step, no rewrap step, no per-file key material to lose, and no migration path to maintain. A database is born encrypted or it does not exist. Losing the master loses the data, which is the property you want from encryption at rest and the reason the master lives in KMS.
The master is process state because that is what it is: one key, injected at boot, for every database this process opens. Threading it through every caller would not make it less global, only harder to see.
The split of responsibilities is deliberate:
namespace names the entity and where its file lives cek turns the master + that name into the file's key, and opens it sqlite opens a file under a raw key and knows nothing about who owns it kms holds the master
Nothing here knows about orgs, users, billing or plugins. It knows a namespace, a subsystem, and a master key.
Index ¶
- Constants
- Variables
- func Convert(ns namespace.Namespace, subsystem, path string) error
- func DeriveKey(master []byte, ns namespace.Namespace, subsystem string) ([]byte, error)
- func HasMaster() bool
- func Open(ns namespace.Namespace, subsystem, dir string) (*sql.DB, error)
- func OpenAt(ns namespace.Namespace, subsystem, path string) (*sql.DB, error)
- func SetDevMaster() ([]byte, error)
- func SetMaster(k []byte) error
Constants ¶
const KeyLen = 32
KeyLen is the length of the master key and of every key derived from it.
Variables ¶
var ErrNoMaster = errors.New("cek: no master key; call SetMaster with 32 bytes from KMS")
ErrNoMaster reports that no master key has been set, or that one of the wrong length was offered.
Open fails with it rather than falling back to an unencrypted file: a service that comes up in plaintext because a key was missing has failed silently at the only thing this package does.
Functions ¶
func Convert ¶ added in v0.2.4
Convert makes the database at path encrypted under the key ns and subsystem derive, in place, without losing a row.
It is IDEMPOTENT and cheap to repeat: a database that is already ciphertext is left untouched and the call costs a stat, so a caller can run it on every boot and stop thinking about which run is the first one.
An absent database is not an error — there is nothing to convert, and Open will create one born encrypted.
func DeriveKey ¶
DeriveKey returns the key for one database: the master, bound to the namespace that owns it and the subsystem it holds.
It is a pure function of its inputs, so the same namespace and subsystem always produce the same key. A file therefore reopens after a restart with nothing persisted beside it, and two databases never share a key because the subsystem is part of the binding.
func HasMaster ¶ added in v0.2.0
func HasMaster() bool
HasMaster reports whether a master key has been installed.
func Open ¶
Open opens the encrypted database holding subsystem for ns, under dir, creating it if it does not exist. The returned handle is already keyed; callers use it as an ordinary *sql.DB.
The location comes from namespace, so a file and its durable slot are two renderings of one name and cannot drift apart.
No error returned here contains the key or a DSN holding it.
func OpenAt ¶ added in v0.2.4
OpenAt opens the encrypted database at path, under the key ns and subsystem derive. It is Open for a store whose LOCATION is settled by something other than the namespace — a mounted volume that an operator points at a fixed place, say, where the file cannot move to suit a naming scheme.
Open is this function over namespace.Path, so there is one derivation and one keyed open, and a store that names its own path gets exactly the encryption every other store gets.
The caller owns the path, and with it the one thing namespace was protecting: two different files opened under the same (ns, subsystem) share a key. Give a store its own subsystem and that cannot arise.
func SetDevMaster ¶ added in v0.2.0
SetDevMaster installs a random master for a process with no KMS — tests, and a laptop. It reports the key it generated so a caller can log that this is what happened. Nothing it writes survives the process, by construction: a new random master cannot open the previous run's files.
Types ¶
This section is empty.