Create a dynamic MySQL or MariaDB secret

Give every machine its own MySQL or MariaDB account, created when it reads the secret and dropped when its time is up.

9 steps8 min readVideo 3:13Updated

A shared database password lives in every app that uses it, and changing it means changing it everywhere at once. A dynamic secret replaces it with an account of its own for each machine: your Burrow creates it in MySQL or MariaDB the moment a machine reads the secret, with only the privileges you choose, and removes it when its time is up. Both work the same way, so this one guide covers them.

What you need#

  • A MySQL or MariaDB database your Burrow can reach, and a role in your Burrow that can write secrets.

  • An admin login there that can create users, ideally one made for your Burrow.

  • Machines with access to the environment the secret goes in. This guide uses api's prod.

Open a new dynamic secret#

Open the environment in Projects, select the + at the top right of the secrets table and choose Dynamic. The dialog has three steps: Connection, Lease & credential, and Review.

Connect to your database#

Name the secret, such as MYSQL. Machines read it as api/prod/MYSQL, like any other secret. Set Provider to the one you run, MySQL or MariaDB: each machine's login is then an account that can connect from any host, 'name'@'%'. The other databases work the same way, each with its own kind of login, and SSH user, below the line, issues SSH certificates instead.

Then fill in where the database is and how your Burrow signs in to it:

  • Host and Port: where your Burrow reaches the database, 3306 by default.

  • Database: the database your Burrow connects to. The grant builder starts on it.

  • Admin user and Admin password: the login your Burrow uses to create and remove each machine's account. It never leaves your Burrow, and machines never see it.

Choose how the connection is protected:

Connection security

What it checks

Encrypted + verified

Encrypted, and the database's certificate must come from a trusted authority and name the host you entered. Best for a database reached over the internet.

Encrypted + trusted certificate

Encrypted, and the certificate must come from a trusted authority, but its host name isn't checked. For a database reached by an address its certificate doesn't name.

Encrypted

Encrypted, without checking the database's identity. The default; works everywhere.

None

Plaintext. Only for a database on a network you trust.

With either checking option, a CA certificate field appears. If your database's certificate comes from your own CA, paste that CA's certificate there. A managed database's certificate is trusted already, so leave it empty.

Select Test connection. Your Burrow signs in with the admin login and checks it can create accounts, by making a throwaway one and dropping it again. Each machine's own account is made when it first reads the secret. Select Continue.

A database on Northwind's own CA: Encrypted + verified, with that CA pasted in.
A database on Northwind's own CA: Encrypted + verified, with that CA pasted in.

Shape each password#

Every account gets its own random password. Under Password, set its length, from 8 to 64, which of A to Z, a to z, 0 to 9 and symbols it uses, and whether to leave out characters that look alike, such as 0 and O. Or choose UUID. The example shows the shape; each account's real password is made when it's issued.

Decide what each login may do#

The grants are SQL, run on each login as it's created, with {{name}} standing for its account. Without any, an account can sign in but can't touch your data. Select Build to write them from a list:

  • Access: Read-only reads rows, Read / write also inserts, updates and deletes them, and Full can change the schema too.

  • Privileges: tick them one by one instead, under Data, Schema changes (creating, dropping and altering tables, indexes, foreign keys and temporary tables) and Routines and views. Any mix that isn't a preset is marked Custom.

  • Scope: the database the grants apply to, the secret's own unless you change it. A grant on a database covers every table in it, including ones created later.

The statement shows as you choose. Use these grants puts it in the grants box. Read / write on app, with Temporary tables ticked for an app whose queries make them, writes this one:

sql
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES ON `app`.* TO {{name}};

Then select Test the grants. Your Burrow makes a throwaway account, applies the grants to it and drops it again, so a typo or a missing table shows up now rather than when a machine reads.

Set the lease policy#

The lease policy decides how each account lives. A new secret starts with sensible defaults, so you may not need to change any of them:

Setting

What it does

Login lasts

How long each account works, from 1 minute to 10 years. 1 hour by default.

Renew on read

A machine that keeps reading keeps its account: a read late in its life extends it by another full lifetime, with the same username and password. The renew window sets how late; at 0, any read after half its life renews it. On by default.

Hard maximum

However often an account is renewed, it gets a fresh password after this long. Off by default.

Revoke when the machine is disabled

Disabling a machine removes its account at once. On by default.

New login after it ends

The first read after an account ends gets a new password under the same username. Switched off, that read is refused. On by default.

New password on every read

Every read sets a new password, so each password is used once. Off by default.

MySQL and MariaDB can't expire an account at a set time, so there's no Database expiry setting here: your Burrow drops each account when its lease ends.

Review and create#

Select Continue to see everything on one page, then Create dynamic secret. The admin password and CA certificate are saved with the secret, encrypted like any other value.

Read it from a machine#

A machine reads a dynamic secret the way it reads a structured one, and gets its own account as fields: host, port, database, sslmode, sslrootcert when you gave a CA, username and password. The username starts with rk_ and names the machine and the secret, so you can pick it out in your database's own list of users.

ratel run sets one variable per field, so MYSQL gives MYSQL_HOST, MYSQL_USERNAME, MYSQL_PASSWORD and so on:

bash
ratel run --env api/prod -- ./server

A machine keeps its account across reads until it ends, and the secret's row counts the logins out. With ratel run --watch, the command restarts when its account gets a new password; a renewal keeps the password, so it restarts nothing.

Change it later#

Choose Configure from the secret's row menu. Each tab saves on its own:

Tab

What you change

Status

Turn issuing off and on. While it's off, machine reads are refused and the row is marked off; accounts already out keep working until they end or are revoked.

Policy

The password and every lease setting. A change applies to accounts issued from then on.

Grants

The grants, with Build and Test the grants. Saving removes the accounts issued with the old grants, and each machine gets a new one on its next read.

Connection

The connection and admin login, with Test connection. The admin password is never shown again; leave it empty to keep the saved one. Saving replaces the accounts the same way.

The connection and grants are kept as the secret's value, so Version History lists every change, and reverting to an earlier one replaces the accounts like any other change.

See and revoke logins#

Choose Logins from the row menu to see every account out: the machine holding it, its username, its state, and when it was issued and ends.

State

Meaning

Issuing

Being created in the database right now.

Active

In use by its machine.

Revoking

Ended, and being removed from the database.

Couldn't remove

Removing it failed. Point at the state to see why; your Burrow keeps trying.

The bin at the end of a row revokes that account now. Your Burrow locks it so it can't sign in, ends its open sessions where the admin login may, and drops it. Its machine gets a new account on its next read.

If a login isn't issued#

The machine's read fails with a database error

Your Burrow couldn't create the account: the database is down, or refuses the admin login. The read fails with the reason, and ratel run doesn't start the command. Open Configure, then Connection, and select Test connection.

Test the grants fails

A statement doesn't apply as written: a typo, a table that doesn't exist, or a privilege the admin login can't grant, which it needs WITH GRANT OPTION. The message names the problem. Fix the grants, or give the admin login the privilege it's missing.

The read is refused

Issuing is turned off on the secret's Status tab, or the machine's account ended while New login after it ends is off.

A login shows Couldn't remove

Your Burrow couldn't remove it: the database couldn't be reached, or the account is the definer of a view, routine, trigger or event, which MySQL and MariaDB won't drop it from under. It keeps trying, waiting longer between tries, up to every 30 minutes. A locked account can't sign in again meanwhile.

Every option in one place: Dynamic secrets in the documentation.

More guides

2:32

Create a dynamic SSH user secret

Give every machine an SSH certificate when it asks for one, log in with plain ssh, and take the login back the moment you revoke it.

8 steps5 min readVideo 2:32
1:51

Set up a certificate authority

Create a certificate authority in your Burrow, attach it to the nodes whose hosts are to trust it, and rotate its key.

5 steps4 min readVideo 1:51