postgres

package
v0.60.0 Latest Latest
Warning

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

Go to latest
Published: Nov 5, 2026 License: AGPL-3.0 Imports: 28 Imported by: 0

Documentation

Overview

Package postgres keeps the records of the API keys in PostgreSQL (ADR 0004), through jackc/pgx: their keyed digests, never the keys.

The schema is changed by versioned SQL migrations embedded in the binary and applied by Migrate, from the admin command with a role that may change it; the API, connected with a role that can only read and write the tables, never migrates. A connection beyond the local machine must verify the server's certificate and host name (sslmode=verify-full), and every query is bounded by queryTimeout on top of its context.

Index

Constants

View Source
const WatchApplicationName = "arnakoff revocation watch"

WatchApplicationName is the application_name of the connection of WatchRevocations, as pg_stat_activity shows it.

Variables

View Source
var ErrBadCA = errors.New("database certificate authority not usable")

ErrBadCA means the certificate authority given with WithCA holds no certificate, or comes with an sslrootcert of the connection string.

View Source
var ErrInsecure = errors.New("database connection without verified TLS")

ErrInsecure means a connection string lets a connection to a remote host go without TLS, or with TLS that does not verify the certificate and the host name: sslmode=verify-full is required beyond the local machine.

View Source
var ErrRestoreInvalid = errors.New("invalid dump")

ErrRestoreInvalid means a dump cannot be restored: not a dump of this format, incomplete, or of a schema newer than the migrations of this binary.

View Source
var ErrRestoreNotEmpty = errors.New("restore target is not an empty key store")

ErrRestoreNotEmpty means the database to restore into already holds keys, or a schema newer than the dump's: a restore never merges nor overwrites.

Functions

func ClassifiedTables added in v0.57.0

func ClassifiedTables() []string

ClassifiedTables returns every table a backup copies or leaves out on purpose. A table of the schema missing from it is a migration that did not say whether its rows are backed up.

func Migrate

func Migrate(ctx context.Context, conn string, opts ...Option) error

Migrate applies every migration not yet applied to the database of conn, one at a time under an advisory lock, so that two runs never interleave. It is run by the administration command with a role that may change the schema, never by the API on start (ADR 0004). Cancelling ctx stops it after the migration in progress.

func ParseConfig

func ParseConfig(conn string, opts ...Option) (*pgxpool.Config, error)

ParseConfig parses a PostgreSQL connection string, URL or key=value, and requires verified TLS (sslmode=verify-full) for every host but the local machine: a loopback address, "localhost" or a Unix socket. Its errors never quote the connection string, which may hold a password.

func Restore added in v0.57.0

func Restore(ctx context.Context, conn string, r io.Reader, opts ...Option) error

Restore loads the dump read from r into the database of conn, checked with opts: it migrates the schema up to the dump's version, loads the rows in one transaction, then applies the remaining migrations. Run it with the role that applies the migrations. The tables of the dump must be empty.

Types

type KeyServices added in v0.51.0

type KeyServices struct {
	// Auth accepts the active keys of the configured environment; a valid
	// key is kept in memory for app.KeyCacheTTL while WatchRevocations
	// listens, and not at all otherwise.
	Auth *app.Authenticator
	// WatchRevocations makes Auth forget each revoked key at once, until
	// ctx is done; it reports each loss of its connection to report.
	WatchRevocations func(ctx context.Context, report func(error))
	// Purge deletes the keys revoked longer than
	// domain.RevokedKeyRetention ago, every app.KeyPurgeEvery.
	Purge *app.KeyPurge
	// Close closes the database, waiting for the connections in use.
	Close func()
	// Store is the database itself: the login requests and the account
	// keys of app.KeyRequests.
	Store *Keys
	// Environment is that of the keys accepted and issued.
	Environment domain.KeyEnvironment
}

KeyServices are the use cases of the API process on the API keys of the configured database, sharing one pool of connections.

func OpenKeyServices added in v0.51.0

func OpenKeyServices(ctx context.Context, cfg config.Config) (KeyServices, error)

OpenKeyServices returns the KeyServices of the configured database. The database is not reached until a key is checked or purged.

type Keys

type Keys struct {
	// contains filtered or unexported fields
}

Keys keeps the records of API keys in the api_keys table, and the login requests in the login_requests table. It implements app.KeyFinder, app.KeyIssuer, app.KeyPurger, app.LoginRequestStore and app.AccountKeyIssuer.

func Open

func Open(ctx context.Context, conn string, opts ...Option) (*Keys, error)

Open returns a Keys on the database of conn, which ParseConfig checks with opts. It does not connect: the first query does, so the API starts and answers 503 while the database is unreachable.

func (*Keys) Close

func (k *Keys) Close()

Close closes every connection, waiting for those in use.

func (*Keys) CreateKey

func (k *Keys) CreateKey(ctx context.Context, r domain.KeyRecord) (domain.KeyRecord, error)

CreateKey stores r and returns it with its identifier set.

func (*Keys) CreateLoginRequest added in v0.52.0

func (k *Keys) CreateLoginRequest(ctx context.Context, r domain.LoginRequest) error

CreateLoginRequest stores r in the login_requests table. It implements app.LoginRequestStore.

func (*Keys) Dump added in v0.57.0

func (k *Keys) Dump(ctx context.Context, w io.Writer) error

Dump writes a dump of the backed-up tables to w, read in one read-only snapshot of the database: the role of the backup may only read (#75). It implements app.BackupDumper.

func (*Keys) EraseAccount added in v0.60.0

func (k *Keys) EraseAccount(ctx context.Context, e domain.Email) (app.PurgeCount, error)

EraseAccount deletes, in one transaction, every key of the account of e, active or revoked, and every login request to it (those stored before migration 0004 excepted: they have no account), and returns how many of each it deleted. It holds the lock of the account, so that no key of it is stored meanwhile by ReplaceAccountKey. Each deleted key is announced on the channel of revocations (migration 0003). It implements app.AccountEraser.

func (*Keys) FindKey

func (k *Keys) FindKey(ctx context.Context, d domain.KeyDigest) (domain.KeyRecord, error)

FindKey returns the record of the key of digest d, or app.ErrKeyNotFound.

func (*Keys) ListKeys

func (k *Keys) ListKeys(ctx context.Context) ([]domain.KeyRecord, error)

ListKeys returns every record, oldest first.

func (*Keys) PurgeLoginRequests added in v0.52.0

func (k *Keys) PurgeLoginRequests(ctx context.Context, cutoff time.Time) (int64, error)

PurgeLoginRequests deletes the login requests whose link was used, or else expired, before cutoff and returns how many it deleted.

func (*Keys) PurgeRevokedKeys added in v0.51.0

func (k *Keys) PurgeRevokedKeys(ctx context.Context, cutoff time.Time) (int64, error)

PurgeRevokedKeys deletes the keys revoked before cutoff and returns how many it deleted. Several instances may run it at once: each deletes what is left.

func (*Keys) ReplaceAccountKey added in v0.52.0

func (k *Keys) ReplaceAccountKey(ctx context.Context, r domain.KeyRecord) (domain.KeyRecord, error)

ReplaceAccountKey revokes at r.CreatedAt every active key of the account r.Email.Account and stores r, in one transaction. A transaction lock on the account serialises two replacements of the same account, so that it keeps one active key. It implements app.AccountKeyIssuer.

func (*Keys) RevokeKey

func (k *Keys) RevokeKey(ctx context.Context, id int64, at time.Time) error

RevokeKey marks the key id revoked at at, or returns app.ErrKeyNotFound. A key already revoked keeps its first revocation time.

func (*Keys) UseLoginRequest added in v0.52.0

func (k *Keys) UseLoginRequest(ctx context.Context, d domain.TokenDigest, at time.Time) (domain.Email, error)

UseLoginRequest marks used at at the request of digest d, unused and unexpired at at, and returns its address, or app.ErrLoginLinkInvalid. One statement checks and marks, so two calls never both succeed.

func (*Keys) WatchRevocations added in v0.52.0

func (k *Keys) WatchRevocations(ctx context.Context, sink RevocationSink, retry time.Duration, report func(error))

WatchRevocations tells sink of the keys revoked in the store until ctx is done, on a connection of its own. When the connection fails, it suspends sink, reports the failure to report and connects again after retry. sink is suspended when it returns.

type Option added in v0.52.0

type Option func(*options)

Option changes how ParseConfig reads a connection string.

func WithCA added in v0.52.0

func WithCA(pem []byte) Option

WithCA verifies the database against the certificates of pem only, instead of the system's: the authority of a managed database instance, which a container cannot mount as the file sslrootcert names. Empty, it changes nothing.

type Restorer added in v0.58.0

type Restorer struct {
	// contains filtered or unexported fields
}

Restorer loads dumps into the database of its connection string with Restore. It implements app.KeyDumpLoader.

func NewRestorer added in v0.58.0

func NewRestorer(conn string, opts ...Option) *Restorer

NewRestorer returns a Restorer into the database of conn, checked with opts. Nothing connects until a dump is loaded.

func (*Restorer) LoadDump added in v0.58.0

func (r *Restorer) LoadDump(ctx context.Context, dump io.Reader) error

LoadDump restores the dump read from r, as Restore does.

type RevocationSink added in v0.52.0

type RevocationSink interface {
	Forget(d domain.KeyDigest)
	Suspend()
	Resume()
}

RevocationSink is told of the keys revoked in the store: Forget for each key, Resume once every later revocation will be told, Suspend as soon as one may be missed. app.KeyCache is one.

Jump to

Keyboard shortcuts

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