GrantForge

    Базы данных / Ключ-значение

    Агент Redis

    Запуск агента Redis рядом с развёртыванием Redis или Valkey, чтобы селекторы ACL каждого пользователя на каждом узле соответствовали политикам GrantForge и заменялись одной командой, спрашивать Redis командой ACL DRYRUN, что разрешают права вне GrantForge, и сообщать об отказах из журналов ACL узлов.

    Агент 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.

    Развёртывание

    1. Добавьте сервис данных redis и настройте его политики. Откройте Права доступа к данным → Агенты, выберите сервис и выпустите токен агента. Он показывается только один раз; сохраните его в файл, который может читать только учётная запись агента.

    2. Создайте пользователя 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
    3. Ограничьте корневые права пользователей, за которыми следит агент, тем, что нужно любому пользователю, например входом; остальное выдаёт агент. Корневые права, дающие больше, обнаруживаются, и о них предупреждается.

      ACL SETUSER alice on >… resetkeys resetchannels -@all +@connection
    4. Напишите файл параметров, заменив примерные адреса, пути и имена:

      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 с обрезкой пробелов.

    5. Запустите агент, например как службу 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 ничего не фильтрует внутри значения и ничего не маскирует.

    Связанные руководства

    Редактировать эту страницу на GitHub