User Management
Readyset keeps its own set of users that are allowed to authenticate with it. That set has two stages in its life: it is seeded from command-line flags the very first time a deployment starts, and from then on you manage it with SQL against a running Readyset, with no restart and no dropped connections.
Bootstrap on the first startup
On a deployment's first startup, Readyset seeds the allowed-users set from two places:
- The user in
--upstream-db-url, so the credentials Readyset already has can also be used to connect to it. --allowed-users(envALLOWED_USERS), a comma-separated list ofusername:passwordpairs.
readyset --upstream-db-url postgresql://readyset:<password>@db.internal/app \
--allowed-users 'alice:<password>,bob:<password>'That start accepts readyset, alice, and bob.
Seeding happens once. Readyset then stores the set and reads it from
storage on every later start, so editing --allowed-users or pointing
--upstream-db-url at a different user has no effect on who may
authenticate. After the first startup, use the commands below.
Managing users at runtime
Connect to Readyset as any allowed user and run:
ALTER READYSET ADD USER 'carol' PASSWORD 'carolpw';
ALTER READYSET MODIFY USER 'carol' PASSWORD 'rotatedpw';
ALTER READYSET DROP USER 'carol';Each command is stored before it returns, so it survives restarts, and takes effect on the next connection attempt: an added user can connect right away, a rotated password is required immediately, and a dropped user is refused. A dropped or rotated user's connections that are already open are not closed; the change applies when they reconnect.
ADD USER fails if the user
already exists;
MODIFY USER and
DROP USER fail if it does not.
The user derived from --upstream-db-url cannot be modified or dropped, since
that identity backs Readyset's own connection to your database. All three
commands require
authentication to be enabled, so they are
unavailable under --allow-unauthenticated-connections.
A user in Readyset also needs to exist in your database with the same
password. Readyset opens each session's connection to your database with
that session's own credentials, so ALTER READYSET ADD USER is a companion
to a CREATE USER upstream, not a replacement for it.
Rotating a password without downtime
Changing a password with MODIFY USER normally requires new connections to
begin using the new password immediately. To allow the old password to remain
valid during a transitional period to the new password, perform:
ALTER READYSET MODIFY USER 'carol' PASSWORD 'rotatedpw' RETAIN CURRENT PASSWORD;Carol can now authenticate with either password. Once all clients have moved to the new one, retire the old password with:
ALTER READYSET MODIFY USER 'carol' DISCARD OLD PASSWORD;A later MODIFY USER ... RETAIN CURRENT PASSWORD replaces any old retained
password with the current password, so only two passwords are ever valid at a
time. MODIFY USER without the clause changes the current password only and
leaves a retained one alone. DISCARD OLD PASSWORD is accepted even if there
is no old password.
To start a deployment already mid-rotation, name the user twice in
--allowed-users. The first password is the current one and the second is the
retained one:
readyset --allowed-users 'carol:newpassword,carol:oldpassword'Password rotation is available with a MySQL upstream only, mirroring MySQL's
own dual-password support. Both clauses, and a repeated user in
--allowed-users, are rejected in PostgreSQL mode.
Rotate the upstream account first, using MySQL's own ALTER USER ... RETAIN CURRENT PASSWORD, and only then run the Readyset statement. Readyset connects
to your database with whichever of the two passwords the client presented, and
checks cache authorization with the current
one, so both passwords must already be valid upstream. When the rotation is
complete, discard the old password in Readyset before discarding it upstream.
Listing the current users
The readyset.users system view lists
the usernames that may authenticate right now, including runtime changes.
Passwords are never exposed.
SELECT "user" FROM readyset.users;user is a reserved word in PostgreSQL, so quote the column there; on MySQL
SELECT user FROM readyset.users works unquoted. The has_old_password column
reports whether the user has a password rotation in progress.
How it fits with the rest of Readyset
Authentication verifies each connection
against this set, whichever method the client protocol negotiates. On MySQL,
caching_sha2_password keeps a per-user fast-auth digest; MODIFY USER and
DROP USER clear it as part of the change, so a rotated password cannot be
bypassed by a client that authenticated earlier. A retained password keeps a
digest of its own until it is discarded.
Cache authorization decides which users
are served from a cache, by asking your database what each of them is allowed
to read. ADD USER and MODIFY USER schedule that check for the new user, so
they start getting cache hits as soon as their privileges are confirmed;
DROP USER forgets them. Until then their queries are simply proxied to your
database.