tools

ACL Builder Applies Redis and Valkey ACL Rules the Way Each Version Does, and Drafts Least-Privilege Users From MONITOR

Redis and Valkey ACL rules are short and easy to get wrong. +@all -flushall and -flushall +@all look alike and grant different things. %R~config:* reads but doesn’t write. A user made on Redis 6.2 may use every Pub/Sub channel, and the same rules on 7.0 give it none. The mistakes show up later, as NOPERM errors in production or as an app user that could have run FLUSHALL all along.

The ACL Builder applies the rules the way the server version you pick does. It gives the error ACL SETUSER would reply with, word for word, or the line ACL LIST would print, and says in plain words what the user can do: which commands, which keys to read or write, which channels, and on Valkey 9.1, which databases.

The ACL Builder checking six commands for a user named app on Redis 8.10.2: GET and SET on app:42 are allowed, while SET config:theme is refused because no key pattern lets the user write it, with the reply ACL DRYRUN gives and the NOPERM error the command would get.

It runs in your browser and doesn’t send anything anywhere, and the page’s security policy stops it from fetching or loading anything from another site. Rules can hold passwords, so that matters.

Will This Command Run?

Type commands the way you’d type them in redis-cli, and each one gets the reply ACL DRYRUN would give and the error the command itself would get. The builder finds the keys of a command the way the server does, from the command’s own description, so it knows that SORT list BY weight_* STORE out writes out and reads list, and that XREAD STREAMS a b 0 0 reads two keys. It checks the errors that come before ACL too: an unknown command, the wrong number of arguments, DEBUG switched off.

A User Built From What the App Does

Least privilege means a user that may do what the app needs and nothing more, and nobody knows offhand what an app needs. MONITOR does. Record a few minutes of the app’s traffic, paste it in, and the builder drafts a user: the commands the app ran, a key pattern for each group of keys, read or write as the app used them, and the channels it published to. Then it checks every line of the capture against the draft. Key patterns made from prefixes are a guess at how the app names its keys, so the builder shows them for you to read before you use them.

The Versions Disagree

The same rules don’t do the same thing everywhere. Redis 7.0 works out the line ACL LIST prints from what the user can do, so rules can come back in another order or another form. From 7.2 they come back as written. A few first arguments, such as +select|a b with a space in it, are accepted by 7.2 and later and then crash the server when it lists the user. Valkey 9.1 adds databases to a user’s rights. The builder shows what every version does with your rules, side by side, which is worth a look before an upgrade.

Checked Against 15 Servers

Redis 6.2 to 8.10 and Valkey 7.2 to 9.1, fifteen versions in all, were built from source and given the same kinds of cases. They answered 71,070 ACL SETUSER calls, about half of them refused and 1,725 of them crashing the server when it listed the user, 150,040 ACL DRYRUN checks, 60,480 commands queued inside MULTI, 90,000 key lookups with COMMAND GETKEYSANDFLAGS, 12,000 ACL files and 7,500 config files. The builder gives the server’s answer to every one of them, the error text byte for byte.

Try It

The builder is one JavaScript file with no dependencies, open source under the Apache License 2.0, and it runs from the command line as well:

node acl/cli.js explain on ">pass word" "~app:*" +@read --server valkey-9.1
node acl/cli.js build monitor.txt --name web

The manual, the tests and the recorded answers they replay are in the acl folder on GitHub.