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
- Variables
- func ClassifiedTables() []string
- func Migrate(ctx context.Context, conn string, opts ...Option) error
- func ParseConfig(conn string, opts ...Option) (*pgxpool.Config, error)
- func Restore(ctx context.Context, conn string, r io.Reader, opts ...Option) error
- type KeyServices
- type Keys
- func (k *Keys) Close()
- func (k *Keys) CreateKey(ctx context.Context, r domain.KeyRecord) (domain.KeyRecord, error)
- func (k *Keys) CreateLoginRequest(ctx context.Context, r domain.LoginRequest) error
- func (k *Keys) Dump(ctx context.Context, w io.Writer) error
- func (k *Keys) FindKey(ctx context.Context, d domain.KeyDigest) (domain.KeyRecord, error)
- func (k *Keys) ListKeys(ctx context.Context) ([]domain.KeyRecord, error)
- func (k *Keys) PurgeLoginRequests(ctx context.Context, cutoff time.Time) (int64, error)
- func (k *Keys) PurgeRevokedKeys(ctx context.Context, cutoff time.Time) (int64, error)
- func (k *Keys) ReplaceAccountKey(ctx context.Context, r domain.KeyRecord) (domain.KeyRecord, error)
- func (k *Keys) RevokeKey(ctx context.Context, id int64, at time.Time) error
- func (k *Keys) UseLoginRequest(ctx context.Context, d domain.TokenDigest, at time.Time) (domain.Email, error)
- func (k *Keys) WatchRevocations(ctx context.Context, sink RevocationSink, retry time.Duration, ...)
- type Option
- type Restorer
- type RevocationSink
Constants ¶
const WatchApplicationName = "arnakoff revocation watch"
WatchApplicationName is the application_name of the connection of WatchRevocations, as pg_stat_activity shows it.
Variables ¶
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.
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.
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.
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 ¶
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 ¶
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
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
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 ¶
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) CreateLoginRequest ¶ added in v0.52.0
CreateLoginRequest stores r in the login_requests table. It implements app.LoginRequestStore.
func (*Keys) Dump ¶ added in v0.57.0
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) PurgeLoginRequests ¶ added in v0.52.0
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
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
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 ¶
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.
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
NewRestorer returns a Restorer into the database of conn, checked with opts. Nothing connects until a dump is loaded.
type RevocationSink ¶ added in v0.52.0
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.