Gratan

MySQL

Manage MySQL users, grants, and privileges as code

Manages
MySQL privileges
Language
Ruby
Package
gratan
CLI
gratan
Config file
Grantfile
The codenize-tools/gratan repository is archived on GitHub (last activity January 2024); the gem still works but no longer receives updates.
Grantfile
user "scott", "%" do
  on "*.*" do
    grant "USAGE"
  end

  on "test.*", expired: '2014/10/08' do
    grant "SELECT"
    grant "INSERT"
  end

  on /^foo\.prefix_/ do
    grant "SELECT"
    grant "INSERT"
  end
end
In short

Gratan is a Ruby command-line tool that manages MySQL users, grants, and privileges as code. You export the current grants into a Grantfile, review edits as Git diffs, then apply them idempotently. A dry-run previews every GRANT and REVOKE before anything changes.

What is Gratan?

Gratan is a command-line tool. It manages MySQL users, grants, and privileges as code. Instead of running GRANT and REVOKE by hand on each server, you write the permissions you want in a Ruby file. This file is called a Grantfile. Gratan then changes MySQL to match it.

Old MySQL servers collect messy privileges over the years. Nobody recalls why a user can write to a schema, and there is no record of changes. Gratan fixes that. The Grantfile lives in Git, so every change is a diff you can review. It follows the standard codenization pattern:

  • Export the grants that already exist.
  • Review each edit as a Git diff.
  • Dry-run to preview the plan, then apply.

Gratan suits DBAs and infrastructure engineers who already keep config in version control. Run PostgreSQL instead? Its sibling Posgra does the same job for Postgres roles and grants.

Key facts
  • Manages MySQL users, grants, and privileges from one Ruby DSL file.
  • Config lives in a file named the Grantfile, kept in version control.
  • A dry-run previews every grant and revoke, and applies are idempotent.
  • Supports regex object matching and expired: dates for time-limited access.
  • Related access-as-code tools include Miam for AWS IAM users and policies.
  • The repository is archived (last active January 2024); the gem still runs.
Illustration: MySQL privileges managed as code with Gratan
Getting started

Install and run Gratan

1

Install

Install the gratan gem (Ruby required).

$ gem install gratan
2

Export current state

Pull the live MySQL configuration into a Grantfile.

$ gratan -e -o Grantfile
3

Dry-run, then apply

Preview the diff, then apply the change for real.

$ gratan -a --dry-run

Gratan uses the export, review, apply loop shared by the codenize-tools family. Start by exporting the live server with gratan -e. It writes every user and grant into a Grantfile. Big installs can be split into many files with --split or --chunk-by-user. Commit that file so your current privileges become a reviewed baseline.

To make a change, edit the Grantfile and run gratan -a --dry-run. Gratan compares the file to the server. It prints the exact GRANT and REVOKE steps it would take, but runs none of them. When the plan looks right, run gratan -a to apply. Applies are idempotent, so running the same file twice changes nothing. A scheduled dry-run also works as a simple drift check for your MySQL privileges.

Pro tip

Run a scheduled gratan -a --dry-run in CI. Any privilege someone added by hand on the server shows up as drift you can review before it becomes permanent.

Capabilities

What Gratan can do

Export existing privileges

The export command dumps every user and grant from a live server into the DSL. Use <code>--split</code> or <code>--chunk-by-user</code> to break big installs into several files.

Idempotent apply with dry-run

<code>gratan -a</code> makes the server match the Grantfile, and a second run does nothing. Add <code>--dry-run</code> to preview the exact grant and revoke steps first.

Regex object matching

Grant blocks accept regular expressions like <code>on /^foo\.prefix_/</code>. One rule can then cover every table that matches a naming pattern.

Grant expiration dates

Users and grants can carry an <code>expired:</code> date. Time-limited access becomes explicit and reviewable instead of relying on memory.

Templates for repeated grants

Since version 0.3.0, <code>template</code> and <code>include_template</code> define a privilege set once. You reuse it across users with per-inclusion values.

Scoping and filter flags

<code>--ignore-user</code>, <code>--target-user</code>, and <code>--ignore-object</code> take regexes. System accounts or specific schemas can be left out of management.

Common MySQL privileges you can grant
A quick reference for the grant keywords used in a Grantfile.
PrivilegeWhat it allows
USAGENo real access; marks that the user exists
SELECTRead rows from tables or views
INSERTAdd new rows
UPDATEChange existing rows
DELETERemove rows
ALL PRIVILEGESEvery privilege on the chosen object
In practice

When teams reach for Gratan

Auditable privilege reviews

Keep the Grantfile in Git and every change becomes a pull request. Reviewers read the diff instead of querying <code>mysql.user</code>, and <code>git blame</code> shows who granted what.

Environment parity

Export grants from production, commit them, and apply the same Grantfile to staging. Gaps between environments show up as dry-run output, not surprise permission errors.

Time-limited access

Grant a contractor <code>SELECT</code> with an <code>expired:</code> date attached. The expiration is visible in review, and the grant does not outlive the work.

Taming inherited servers

On a legacy database, one export gives you a full inventory of grants. From there you prune unused accounts in small, dry-run-checked steps.

FAQ

Gratan questions, answered

Is Gratan still maintained?
No. The gratan repository was archived on GitHub after its last activity in January 2024. The gem still installs and works against MySQL, but expect no new releases. For a maintained option, look at the Terraform MySQL provider.
What happens to grants that are not in the Grantfile?
Gratan is declarative. It makes the server match the file, so grants on the server but missing from the file get revoked on apply. Use --ignore-user or --target-user to scope what it manages, and always check --dry-run first.
How does Gratan connect to MySQL?
Through flags like --host, --port, --username, and --password, or the matching GRATAN_DB_* environment variables. It uses the mysql2 driver, and --mysql2-options takes extra options as JSON.
Can Gratan manage user passwords?
Yes, within limits. Grants can carry an identified: value, and options like --auto-identify and --csv-identify help set passwords in bulk. Hashed secrets export as placeholders, so many teams manage passwords outside the Grantfile.
Is the dry-run safe to point at production?
Yes. With --dry-run, Gratan only reads the current grants and prints what it would do. Nothing runs. That makes it useful for both change previews and drift detection.