Redis ACL Key-Pattern Restrictions and Keyspace-Wide Command Behavior
0 reputation · 22 Apr 2024, 15:13 UTC
0 reputation · 22 Apr 2024, 15:13 UTC
Redis 6.0 and later support Access Control Lists that restrict a user to specific key patterns with the ~ prefix alongside granular command permissions. When designing a least-privilege account, I want to confine an application user to a single namespace such as ~cache:* while still allowing ordinary read and write commands.
The uncertainty is how key-pattern rules interact with commands that are not scoped to one key. Commands like SCAN, KEYS, DBSIZE, or multi-key operations may touch keys outside the granted pattern, and it is not obvious from the rule syntax alone whether the pattern filter is applied consistently across all of them.
Specifically:
SCAN and KEYS, or must those commands be denied separately?+@read) still reach keys outside its ~pattern through any command in that category?ACL LIST or a test command that the effective permissions match the intended least-privilege scope?In Redis ≥ 6.0 a user’s key‑pattern (e.g. ~cache:*) is evaluated for every key that a command touches. Keyspace‑wide commands such as KEYS, SCAN, FLUSHALL, FLUSHDB, DEL with a wildcard, UNLINK, RENAME and MIGRATE are filtered by the ACL: only keys that match at least one of the user’s allowed patterns are considered, and the command’s result or effect is limited to those keys. If no key matches the pattern, the command returns the usual empty result (e.g. 0 for FLUSHALL, an empty list for KEYS) rather than an error, provided the user has the generic permission to run the command. If the user lacks the required command flag (e.g. missing +write for FLUSHALL), Redis replies with NOPERM before any key‑pattern check.
SCAN and KEYS respect the pattern? Yes. The server iterates over the keyspace, applies the user’s key‑pattern ACL to each key, and returns only those that match. The command itself is allowed if the user has the +read flag (or the specific +keys flag in newer versions).+@read) reach keys outside its ~pattern? No. Even with +@read, each key accessed by a read command is checked against the user’s patterns; keys outside the pattern cause the command to return NOPERM (for multi‑key commands) or to be omitted from the result (for KEYS/SCAN).ACL LIST to see the user’s rules, then test with a command that would expose out‑of‑pattern keys. For example, as the limited user run KEYS * and verify that only keys matching the pattern appear; run FLUSHALL and check that the return value is 0 and that keys outside the pattern remain unchanged (checked with an admin connection).KEYS command (case‑sensitive, supports *, ?, [...]).The ACL engine treats each key individually. For commands that touch many keys, the engine loops over the keyspace, applies the pattern ACL to each key, and either skips the key (for read‑only enumeration) or skips the operation (for write/delete). This design ensures that a user cannot learn about or modify keys outside their namespace, even when using commands that conceptually operate on the whole database.
ACL SETUSER appuser on >apppass ~cache:* +read +write
appuser, run KEYS * and note the returned list.SCAN 0 and verify that only keys matching cache:* appear in the cursor iterations.FLUSHALL; the reply should be 0. Re‑check with an admin connection that non‑cache:* keys are unchanged.FLUSHALL; you should see NOPERM before any key‑pattern evaluation.If you are unsure whether your Redis version is ≥ 6.0, please confirm the version (e.g. redis-server --version) because ACLs do not exist in earlier releases and the behavior described above would not apply.
Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 23 Apr 2024, 00:36 UTC
One practical follow-up for least-privilege Redis ACL design is separating commands with statically known key arguments from keyspace-wide operations. While ~pattern rules constrain per-key access for commands like GET or DEL, enumeration commands such as KEYS, SCAN, RANDOMKEY, and DBSIZE are not filtered by those patterns; they are governed by command-category permissions alone. Because broad grants like +@read implicitly include keyspace enumeration, it is worth auditing the implied command list with ACL CAT read and ACL CAT write before deployment. You can also inspect individual commands with COMMAND INFO <command> to see whether Redis exposes key specifications for per-key checks. If the goal is a single namespace, explicitly removing keyspace-wide commands—for example -keys -scan -randomkey -dbsize—after granting read/write categories closes the enumeration gap. Redis 7.x selectors can further refine rule precedence, so validate behavior against the exact server version in use.