Skip to main content

Access Control Lists (ACL)

Dragonfly has built-in support for ACL. Dragonfly operators get fine-grained control over how and who accesses the datastore via the ACL family of commands. Since Dragonfly is designed as a drop-in replacement for Redis, you can expect the same API functionality for ACL as in Redis.

All connections in Dragonfly default to the user default (unless that user is disabled). By default, user default can AUTH in Dragonfly using any password, and is allowed to execute any command and is part of all the available ACL groups.

Permissions for a given user are controlled via a domain-specific language (DSL) and are divided into four categories:

  1. ACL Groups
  2. Command Rules
  3. Key Permissions
  4. Pub/Sub Permissions

Granting or revoking permissions for a user is as easy as calling the ACL SETUSER command. For example:

ACL SETUSER John ON >mypassword +@ADMIN +SET

If the user John does not exist, then the user is created with the permissions specified in the argument list of the command. Otherwise, SETUSER acts as an update of the entry (and its permissions) for that user.

A user can be ON or OFF. By default, all users (except default) are OFF (unless you explicitly grant them ON). The ON/OFF mechanism grants or revokes the user the ability to authenticate in the system using the AUTH command.

Passwords

A password can be set using the > character followed by the password. For example: ACL SETUSER Mike >mypassword, creates the user Mike with pass mypassword. Currently, each user can have only one password.

The special word nopass allows the user to AUTH using any password.

Note that subsequent uses of > on already existing users, update the password.

Authentication

Users can use AUTH <username> <password> to authorize their connection with a given user. After that, all of the commands issued within a connection will abide by the user's specified permissions. Changing the default user's status to OFF or password, will require all incoming connections to authenticate.

Note that if the password is changed and a user has already authenticated then they don't need to re-authenticate until they reconnect. Basically, password change does not act as a connection eviction mechanism. However, if the ACL DELUSER is used to remove the user from the system, then their connection is killed by the system. Furthermore, any change to a user's permission list with ACL SETUSER will propagate to the already active and authenticated connections.

Also note that the flag --requirepass also changes the default user password. So, if during Dragonfly startup the flag requirepass is set, then the default user's password will be the one specified in that flag.

ACL Groups

Each command belongs to a set of ACL groups. The syntax for specifying a group is:

+@GROUP_NAME
-@GROUP_NAME

The sign at the front dictates the operation (+ for granting and - for revoking). The @ denotes category (ACL group) and the GROUP_NAME is the name of the group. For example:

ACL SETUSER John ON +@FAST

Updates the permissions of user John and grants him the ability to run any command in the group FAST. Revoking this, is straightforward:

ACL SETUSER John -@FAST

There are also the special keywords +@ALL, -@ALL that allow the user to run commands found in ALL GROUPS.

With @ALL it's possible to do:

ACL SETUSER John +@ALL -@ADMIN -@FAST

Which basically grants all but the @ADMIN and @FAST groups to the user. That way, it's easy to express which groups of permissions the user should not be a part of. The list of all categories is accessible with the command ACL CAT and user specific information is accessible with the command ACL GETUSER <username>.

Command Rules

Dividing the commands into groups offers a great flexibility of quickly granting/revoking permissions, but it's somehow limited because these groups are not user defined. Therefore, for finer control, the user can specify a list of commands that is explicitly allowed to execute. For example:

ACL SETUSER John +GET +SET +@FAST

This allows the user John to execute only the SET and GET commands and all the commands associated with the group FAST. Any attempt of user John to issue a command other than the above will be rejected by the system.

Note that the syntax is similar to the ACL groups, but without the prefix @.

The special +ALL (note without the @) is used to denote all the currently implemented commands.

Key Permissions

It's also possible to restrict operations on given keys. Note, users are permitted to execute a command only when their ACL's both include that command (or group) and contain a key pattern that matches the keys of the command. Key patterns are:

  • ~<pattern>: Add a pattern of keys that can be mentioned as part of commands. For instance ~* allows all the keys. The pattern is a glob-style pattern, and it is possible to specify multiple patterns.
  • %R~<pattern>: Add the specified read key pattern. This behaves similar to the regular key pattern but only grants permission to read from keys that match the given pattern.
  • %W~<pattern>: Add the specified write key pattern. This behaves similar to the regular key pattern but only grants permission to write to keys that match the given pattern.
  • %RW~<pattern>: Alias for ~<pattern>.
  • allkeys: Alias for ~*.
  • resetkeys: Removes all the key patterns from the list of key patterns the user can access.

Pub/Sub Permissions

Pub/Sub commands are a separate category, and it's possible to restrict operations on specific channels. Just like Keys, Pub/Sub commands use a glob-style pattern to control access to channels.

  • &*: Grants access to all pub/sub channels.
  • &<pattern>: Grants access to channels with names specified by the <pattern>.
  • resetchannels: Revokes access to all channels. The user can't access, publish, or subscribe to any channel.
  • allchannels: Alias for &*.

Note: For all command variants that start with P (like PSUBSCRIBE), the match must be a literal match. For example, if a user's ACL contains the pattern &fo& and the user tries to PPSUBSRIBE foo, it would fail. However, if the user's ACL contains the pattern &foo instead, it would pass. This restriction does not exist on the rest of the family of pub/sub commands.

Persistence

The state of all the users and their permissions can be captured and placed in a file. As with redis, the --aclfile option is used to specify the file from which Dragonfly will load the ACL state from.

Afterwards, any change done at runtime, can be persisted at anytime via the command ACL SAVE which evicts the currently stored ACL state to the file specified in the --aclfile option.

Note, that the aclfile file is compatible with Redis (however it must not contain any keys or pub/sub DSL's because these yet are not supported so if you plan to migrate, just open the file and strip them away).

If you want the aclfile to be writable, that is, if you want ACL SAVE to work, we would advise against placing the aclfile under /etc directory because usually that directory is only accessible by Dragonfly as readonly. You change this behavior, by editing the systemd service file located in /lib/systemd/system/dragonfly.service.

For convenience, we suggest to place acl files in /var/lib/dragonfly/.

Logs

All connections that fail to authenticate and all the authenticated users who fail to run a command (because of their permissions) are stored in a log. The size of the log can be configured by the option --acllog_max_len. This flag, operates a little bit differently from Redis. Specifically, because Dragonfly uses a shared nothing thread per core architecture, each thread of execution has its own log. Therefore, the total size of the log entries, is the flag number multiplied by the available number of Dragonfly threads. So for example, if you are running Dragonfly with 4 threads with --acllog_max_len=8 then the total number of log entries stored in the system at any time can be 32 and each core can store up to 8 entries. When the per-thread threshold is reached, each new log entry will cause the oldest one to get evicted.

Log information can be printed via the command ACL LOG.