Агент Redis — это сервис рядом с развёртыванием. Он поддерживает собственный ACL Redis в соответствии с подписанными политиками сервиса данных redis на каждом узле, включая реплики и все узлы кластера, так как Redis ведёт ACL на каждом. Затем Redis сам проверяет каждую команду, а агент не стоит на пути ни одного клиента. Дистрибутив поставляет его как исполняемый JAR agents/redis/grantforge-agent-redis-<version>.jar; нужна Java 17 или новее.
Интеграционные тесты Testcontainers в репозитории запускают агента и поставляемый JAR на первичном узле с репликой Redis 7.2, 7.4, 8.2 и 8.10 и Valkey 8.1 и 9.1, а также на кластере Redis 8.10. Это не сертифицирует все остальные версии; агент отклоняет Redis старше 7.2, журнал ACL которого не нумерует записи. О сервисном плагине см. Redis.
Как это работает
- Селекторы принадлежат GrantForge, корневые права — администратору. Redis разрешает команду, если её разрешают корневые права пользователя или один из его селекторов. Агент ведёт все селекторы пользователей, за которыми следит, и никогда не трогает их корневые права и пароли: один селектор содержит ключи, которые пользователь может читать, записывать или и то и другое, один — каналы, на которые он может подписываться, один — те, в которые может публиковать, и на узлах, которые он может отслеживать, ещё один.
- Изменение выполняется одной командой.
ACL SETUSER user clearselectors (…)разом заменяет все селекторы пользователя на узле, так что у пользователя никогда не бывает одновременно старых и новых или ни тех, ни других; изменённые вручную селекторы исправляются так же при следующей синхронизации. - Шаблоны — только там, где они верны. Шаблон ключей или каналов из политики выдаётся как собственный шаблон Redis там, где политики решают для пользователя одинаково по всему шаблону; агент разрезает шаблон по каждой пересекающейся с ним политике и решает каждую часть, так что политика другого пользователя его не блокирует. Шаблон, внутри которого политики решают иначе, не выдаётся и один раз записывается в журнал.
- Ничего опасного, никакого перечисления чужих ключей. Селекторы никогда не дают того, что Redis считает опасным, а
SCANиRANDOMKEYдают только пользователю, который может читать все ключи. - Каждый узел, сохранение где возможно. Агент находит реплики и узлы кластера по указанным узлам и приводит каждый в соответствие. Узел, хранящий ACL в файле, сохраняет его командой
ACL SAVE; узел без файла теряет селекторы при перезапуске и снова получает их при следующей синхронизации. - Redis спрашивают, что он разрешает. Корневые права решают наряду с селекторами агента. Вместо чтения их правил агент спрашивает Redis командой
ACL DRYRUN, может ли пользователь выполнить команду над ключом, каналом или узлом, запрещённым ему политикой, и по одному разу предупреждает, называя пользователя, доступ и политику. Он также предупреждает о пользователях, которых не ограничивает ни один селектор, с любыми командами над любыми ключами, и о пользователях, под которыми любой может войти без пароля. - Отказы берутся из журнала ACL каждого узла. См. раздел «Сообщения об отказах» ниже.
- Политики текущего момента. Каждая синхронизация планирует по политикам, действующим в этот момент, так что сроки действия начинаются и заканчиваются вовремя, и по пользователям и узлам, которые есть в Redis.
Развёртывание
-
Добавьте сервис данных
redisи настройте его политики. Откройте Права доступа к данным → Агенты, выберите сервис и выпустите токен агента. Он показывается только один раз; сохраните его в файл, который может читать только учётная запись агента. -
Создайте пользователя ACL для агента на каждом узле. Он читает пользователей, задаёт их селекторы, сохраняет файл ACL, читает журнал ACL, выполняет пробные запуски и находит узлы кластера.
+acl|setuserможет выдать себе что угодно, поэтому защищайте этого пользователя как администратора.ACL SETUSER grantforge on >… -@all +@connection +acl|whoami +acl|users +acl|getuser +acl|setuser +acl|log +acl|dryrun +acl|save +config|get +info +cluster|nodes +command|info -
Ограничьте корневые права пользователей, за которыми следит агент, тем, что нужно любому пользователю, например входом; остальное выдаёт агент. Корневые права, дающие больше, обнаруживаются, и о них предупреждается.
ACL SETUSER alice on >… resetkeys resetchannels -@all +@connection -
Напишите файл параметров, заменив примерные адреса, пути и имена:
grantforge.server.url=https://grantforge.example.com grantforge.token.file=/etc/grantforge/redis-agent.token grantforge.instance=redis-agent-1 grantforge.cache.dir=/var/lib/grantforge/redis-agent grantforge.redis.nodes=redis1.internal:6379,redis2.internal:6379 grantforge.redis.user=grantforge grantforge.redis.password.file=/etc/grantforge/redis-agent.passwordЭти пути находятся на машине агента, а каталог кэша должен быть доступен для записи. Файлы паролей читаются в UTF-8 с обрезкой пробелов.
-
Запустите агент, например как службу systemd:
java -jar agents/redis/grantforge-agent-redis-<version>.jar /etc/grantforge/redis-agent.propertiesЗамените
<version>версией дистрибутива. Параметры, переданные какjava -Dgrantforge.…=… -jar …, переопределяют файл. По SIGTERM агент корректно останавливается и отправляет или откладывает ожидающие события; Redis сохраняет то, что получил.
| Параметр | Назначение |
|---|---|
grantforge.server.url, grantforge.token.file, grantforge.instance, grantforge.cache.dir |
Обязательно: сервер GrantForge, файл токена агента, имя этого агента и доступный для записи каталог для подписанного снимка, отложенных событий и позиции чтения журнала аудита |
grantforge.signing.key.file |
Необязательный файл, закрепляющий ключ подписи снимков; скопируйте открытый ключ X.509 Ed25519 в Base64 со страницы «Агенты». Если не задан, ключ берётся с сервера при первом обращении |
grantforge.redis.nodes |
Обязательно: узлы в виде host:port, без порта — 6379 |
grantforge.redis.discover |
По умолчанию true: остальные узлы кластера и реплики первичного узла находятся по указанным узлам. false берёт только указанные узлы — когда объявляемые узлами адреса недоступны агенту |
grantforge.redis.user, grantforge.redis.password.file |
Пользователь ACL агента, пусто — пользователь по умолчанию, и его пароль |
grantforge.redis.tls.mode, grantforge.redis.tls.ca.file, grantforge.redis.tls.certificate.file, grantforge.redis.tls.key.file, grantforge.redis.tls.key.password.file |
disable (по умолчанию), verify-ca или verify-full; PEM-сертификаты ЦС для проверки серверов, пусто — то, чему доверяет Java; клиентский PEM-сертификат, его ключ, если он в отдельном файле, и пароль ключа |
grantforge.redis.timeout.ms |
Сколько могут занимать подключение и одна команда, по умолчанию 10000, в диапазоне 1..600000 миллисекунд |
grantforge.redis.unmanaged.users |
Пользователи, которых агент не трогает, через запятую, например служебные учётные записи. Он никогда не трогает собственного пользователя и пользователей с любыми командами над любыми ключами |
grantforge.sync.interval.ms |
Как часто агент приводит Redis в соответствие, по умолчанию 10000, диапазон 1000..3600000 миллисекунд |
grantforge.audit.log, grantforge.audit.log.interval.ms |
По умолчанию true; false не читает журнал ACL. Как часто читать журналы ACL, по умолчанию 5000 миллисекунд |
grantforge.connect.timeout.ms, grantforge.read.timeout.ms |
Тайм-ауты подключения и чтения GrantForge, по умолчанию 5000 / 8000 миллисекунд |
grantforge.refresh.interval.ms |
Как часто агент запрашивает новые политики, по умолчанию 30000, не менее 1000 миллисекунд |
grantforge.audit.batch.size, grantforge.audit.queue.capacity, grantforge.audit.flush.interval.ms, grantforge.audit.spool.limit.bytes |
События доступа: размер пакета (по умолчанию 500), размер очереди (по умолчанию 10000), интервал отправки (по умолчанию 5000 миллисекунд) и предел отложенного на диске (по умолчанию 64 МиБ) |
grantforge.audit.fold.window.ms |
Сколько времени одинаковые разрешённые обращения сворачиваются в одно событие, по умолчанию 10000, до 3600000 миллисекунд; 0 — отправлять каждое |
Сообщения об отказах
Redis не записывает, что он разрешил, поэтому агент сообщает о том, в чём он отказал, из журнала ACL каждого узла: кому в чём отказано, откуда и когда, и решают ли политики так же, как Redis. Redis объединяет отказ, повторившийся в течение минуты, с предыдущей записью; агент сообщает о записи снова при каждом её обновлении.
| Причина в журнале | Событие доступа |
|---|---|
key |
read или write для ключа — по тому, как Redis помечает команду |
channel |
subscribe или publish для канала |
command |
monitor для узла — для команд мониторинга; остальные команды записываются без ключей и не сообщаются |
auth |
Не сообщается: отклонённый вход не называет никакого доступа |
Пользователи, группы и роли
Политики называют пользователей ACL Redis по имени. У Redis нет собственных ролей и групп, поэтому группы — это те, в которые пользователей помещает GrantForge.
Решения и ограничения
- Без снимка агент ничего не меняет. Токен, привязанный к неиспользуемому сервису или к сервису не типа
redis, ничего не выдаёт: агент очищает селекторы пользователей, за которыми следит. - Пока агент не работает, Redis сохраняет полученное последним, а изменения политик ждут. Изменение доходит до Redis в пределах интервалов обновления и синхронизации.
- Агент ведёт все селекторы пользователей, за которыми следит: селектор, добавленный администратором вручную, удаляется при следующей синхронизации. Дополнительные права выдавайте в корневых правах или оставьте пользователя администратору.
- ACL Redis называет ключи и каналы, а не базы, поэтому шаблон охватывает свои ключи во всех базах узла.
- Отказ в команде, которую пользователь вообще не может выполнять, Redis записывает без ключей, и о нём не сообщается.
- Redis ничего не фильтрует внутри значения и ничего не маскирует.
