GrantForge

    Плагины

    Агент Apache Hadoop HDFS NameNode

    Применение политик GrantForge агентом NameNode для соответствующей версии Hadoop и отправка аудита доступа.

    Серверный плагин grantforge-plugin-hdfs задаёт ресурсы и подключения. Нумерованные агенты NameNode для Hadoop 2.7, 2.10, 3.2, 3.3, 3.4 и 3.5 проверяют доступ через SPI своей версии и разделяют логику подписанных снимков, оценки политик и отправки аудита.

    Общая логика HDFS находится в agents/grantforge-agent-hdfs-common, адаптеры версий — в agents/grantforge-agent-hdfs-<line>. Общие нативные адаптеры входят в производственный Maven-модуль agents/grantforge-agent-hdfs-native на базе Java 8 / Hadoop 2.7.7. Нумерованные модули используют его бинарную Maven-зависимость и сохраняют свои точки входа и специфичные для версии callbacks, не перекомпилируя общие производственные исходники. core/grantforge-agent-core остаётся общей библиотекой протокола и выполнения.

    Серверный плагин сохраняет единый тип службы hdfs, а версия клиента не зависит от агентов. Для подключения и поиска путей в Hadoop 2.x используйте webhdfs://namenode:50070 или соответствующий адрес swebhdfs:// с HTTPS. Hadoop 3.x может использовать RPC hdfs:// или WebHDFS. Контейнерные тесты проверяют WebHDFS на 2.x и оба протокола на 3.x. RPC на 2.x не сертифицирован; настроенный протокол не меняется автоматически.

    При включённых расширениях атрибутов inode Apache Hadoop 2.7.7 вызывает нативную ошибку нулевого указателя при запросе / обычным пользователем, до вызова агента. Для операций с данными и lookup.path в этой версии используйте каталоги данных, например /data. Контейнерный тест явно проверяет это ограничение корневого пути.

    Целевые версии агентов HDFS

    Базовая версия Hadoop Java контейнера Каталог агента
    2.7.7 Java 8 agents/hdfs/2.7/
    2.10.2 Java 8 agents/hdfs/2.10/
    3.2.4 Java 8 agents/hdfs/3.2/
    3.3.6 Java 8 (образ amd64) agents/hdfs/3.3/
    3.4.3 Java 11 agents/hdfs/3.4/
    3.5.0 Java 17 agents/hdfs/3.5/

    Выберите grantforge-agent-hdfs-<line>-<GrantForge-version>.jar из agents/hdfs/<line>/ для ветки Hadoop вашего кластера. Общая логика рассчитана на Java 8, адаптер 3.5 — на Java 17.

    Hadoop 2.7, 2.10, 3.2 и 3.3 не предоставляют используемый агентом callback авторизации суперпользователя. Hadoop сохраняет контроль этих обращений; для данных, регулируемых политиками GrantForge, используйте обычных пользователей.

    Соотношение с встроенными правами

    Следующее поведение относится к обращениям обычных пользователей. Ограничения суперпользователя описаны выше и в разделе его callbacks.

    Агент сначала выполняет встроенные проверки прав HDFS, затем — политики GrantForge: пользователь должен удовлетворять и тем, и другим. Разрешающие политики GrantForge не отменяют POSIX-права, ACL, проверку владельца или sticky bit; запрещающие политики всегда запрещают. Встроенные настройки прав по-прежнему администрируются средствами Hadoop.

    Значение по умолчанию grantforge.hdfs.native.fallback=false запрещает доступ к данным, когда нет локального снимка политики, нет подходящей политики или агент ещё не запущен. При true доступ, не решённый политиками, определяется встроенными правами; явные запрещающие политики действуют независимо от этого. Пока сервер временно недоступен, агент продолжает использовать последний локальный снимок, прошедший проверку подписи.

    Предки, цель, поддеревья и проекции путей снимка внутри одного обратного вызова авторизации используют одну и ту же версию снимка политики; обновлённые политики вступают в силу со следующего вызова, поэтому правила разрешения из разных версий никогда не смешиваются. Записи аудита доступа фиксируют фактически использованную версию политики.

    Агент проверяет права read, write и execute, которые нужны обычному пользователю для цели, а также родительские каталоги, каталоги-предки и подкаталоги, требующие рекурсивной проверки. Операции создания, удаления и переименования затрагивают несколько путей, и разрешающие политики должны покрывать все их. В строгом режиме одной политики read на целевой файл недостаточно: пользователю также нужны политики execute на каталогах-предках — например, разрешите execute на / с включённой рекурсией, а затем настройте чтение и запись на реальных каталогах данных.

    Пути снимков проверяются и как фактически запрошенный путь, и как исходный путь с удалённым .snapshot/<snapshot name> — например, /data/.snapshot/s1/secret также проверяется как /data/secret. Поэтому запрещающие политики для исходного пути ограничивают и снимки; для явных путей снимков можно дополнительно настроить более строгие ограничения. Запросы метаданных следуют семантике прав при обходе каталогов HDFS.

    Одна рекурсивная авторизация проверяет не более 100000 инодов; при превышении предела операция запрещается, чтобы избежать неограниченного выделения памяти внутри NameNode. Слишком длинные пути оцениваются по полному пути; отображение ресурса в аудите ограничено 1000 символами, а исходная длина и дайджест SHA-256 записываются в деталях запроса.

    Следующие callbacks суперпользователя относятся к Hadoop 3.4 и 3.5. Суперпользователи HDFS по-прежнему администрируются Hadoop. Обратные вызовы суперпользователя с путём сначала проходят проверку суперпользователя Hadoop, затем проверяются по политикам согласно именам операций, предоставляемым Hadoop 3.4 / 3.5: чтение файлов и запросы метаданных требуют read, перечисление каталогов — read + execute, а известные операции изменения — write. Неизвестные, отсутствующие или ненадёжно определяемые операции (например, checkAccess и concat) консервативно требуют всех трёх прав.

    У обратных вызовов суперпользователя нет полного контекста инодов и поддеревьев, а вызовы администрирования кластера без пути сохраняют встроенные проверки; ни одну рекурсивную операцию суперпользователя нельзя ограничить политиками подкаталогов. Потребителям данных следует пользоваться обычными пользователями Hadoop.

    Метрики

    Агент сообщает свои метрики через систему Metrics2 Hadoop, по тем же sink'ам, что и собственные dfs-метрики NameNode: в JMX NameNode они зарегистрированы как Hadoop:service=NameNode,name=GrantForgeHdfsAgent (Prometheus JMX exporter может собирать их напрямую). Каждая метрика несёт теги instance (экземпляр сервиса данных) и agentVersion, поэтому два NameNode в паре HA можно различить. Неудачная регистрация стоит только метрик: агент пишет предупреждение и продолжает принуждение без них.

    Метрика Значение
    Callbacks Обратные вызовы авторизации, обработанные агентом
    SuperuserCallbacks Обратные вызовы авторизации суперпользователя, обработанные агентом (3.4 / 3.5)
    NativeDenies Попытки доступа, отклонённые Hadoop до запуска агента
    EvaluationFailures Вызовы, завершённые отказом, из-за исключения при оценке политики
    DecisionsAllowed / DecisionsDenied / DecisionsUndetermined Разрешённые / отклонённые / оставленные без решения политикой права; в строгом режиме «без решения» тоже отклоняется
    MissingSnapshots Обслуженные вызовы в отсутствие проверенного снимка политики
    SnapshotVersion Версия политики используемого снимка, 0, если снимка нет
    QueuedEvents / DroppedEvents События доступа, ожидающие в памяти / потерянные из-за заполнения очереди или дискового буфера
    ServerReachable Успешен ли последний вызов сервера политик (1/0)

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

    1. Добавьте сервис hdfs в разделе сервисов данных GrantForge, сохраните конфигурацию и проверьте подключение; настройте политики путей для реальных коротких имён пользователей Hadoop, групп или ролей.
    2. В разделе «Права на данные → Агенты» выпустите токен для этого сервиса. Запишите сырой токен в локальный файл на каждом NameNode, например /etc/hadoop/grantforge/token, доступный для чтения пользователю, от имени которого работает NameNode.
    3. Выберите ветку Hadoop кластера и скопируйте grantforge-agent-hdfs-<line>-<GrantForge-version>.jar из agents/hdfs/<line>/ в classpath NameNode, например $HADOOP_HOME/share/hadoop/hdfs/lib/. Установите только один подходящий адаптер. Jar включает общую логику, Jackson и библиотеку подписей; Hadoop предоставляется NameNode.
    4. Настройте следующие свойства в hdfs-site.xml каждого NameNode; два NameNode в конфигурации HA используют разные значения instance и собственные каталоги локального кэша.
    <property>
      <name>dfs.namenode.inode.attributes.provider.class</name>
      <value>org.devlive.grantforge.hdfs.agent.HdfsAuthorizationProvider</value>
    </property>
    <property>
      <name>grantforge.hdfs.server.url</name>
      <value>https://grantforge.example.com/</value>
    </property>
    <property>
      <name>grantforge.hdfs.token.file</name>
      <value>/etc/hadoop/grantforge/token</value>
    </property>
    <property>
      <name>grantforge.hdfs.instance</name>
      <value>namenode-1</value>
    </property>
    <property>
      <name>grantforge.hdfs.cache.dir</name>
      <value>/var/lib/hadoop/grantforge</value>
    </property>
    <property>
      <name>grantforge.hdfs.native.fallback</name>
      <value>false</value>
    </property>
    1. Убедитесь, что dfs.permissions.enabled=true, а dfs.namenode.inode.attributes.provider.bypass.users пуст; при запуске агент отклоняет конфигурации, позволяющие обходить обратные вызовы авторизации. Перезапустите NameNode, затем проверьте heartbeat и версию политики на странице агентов GrantForge. Агент читает существующую конфигурацию NameNode; он не изменяет встроенные атрибуты инодов.

    Для первого развёртывания можно начать с native.fallback=true, убедиться, что снимок политики синхронизирован, а права каталогов-предков заданы полностью, и лишь затем перейти в строгий режим. Тип сервиса, с которым связан токен, должен быть hdfs; при ошибке конфигурации или привязке к другому типу сервиса доступ запрещается.

    Дополнительные настройки

    Свойство По умолчанию Назначение
    grantforge.hdfs.connect.timeout.ms 5000 Тайм-аут подключения к GrantForge
    grantforge.hdfs.read.timeout.ms 8000 Тайм-аут чтения ответа
    grantforge.hdfs.refresh.interval.ms 30000 Интервал обновления политики, пока сервер недоступен, не менее 1000; обычные heartbeat'ы используют интервал, предложенный сервером
    grantforge.hdfs.signing.key.file не задан Необязательный файл открытого ключа подписи с открытым ключом Base64 X.509, выданным консолью; при настройке принимаются только подписи этим ключом
    grantforge.hdfs.audit.batch.size 500 Максимальное число событий в одном отчёте, диапазон 1..1000
    grantforge.hdfs.audit.queue.capacity 10000 Ёмкость очереди аудита в памяти, диапазон 1..1000000, должна вмещать хотя бы один пакет; при заполнении очереди новые события подсчитываются и отбрасываются
    grantforge.hdfs.audit.flush.interval.ms 5000 Интервал сброса аудита, положительное целое число, не более 2147483647; уменьшите его, чтобы снизить задержку отправки
    grantforge.hdfs.audit.spool.limit.bytes 67108864 Предел дискового буфера, пока сервер недоступен, неотрицательное целое число; 0 отключает дисковый буфер

    При всплесках нагрузки увеличьте очередь аудита, чтобы уменьшить переполнение; уменьшение интервала сброса снижает задержку аудита, но увеличивает частоту отправки. Предел дискового буфера контролирует использование диска при длительных отключениях; события могут теряться, если буфер отключён или исчерпан. Отправка аудита выполняется в фоновом режиме и не ждёт ответа сервера политик.

    Если открытый ключ подписи не настроен, агент при первом обращении запрашивает его у сервера и хранит вместе со снимком. Агент использует короткое имя пользователя и группы, переданные Hadoop; роли и дополнительные группы поступают из подписанного снимка. Сопоставление коротких имён для principal'ов Kerberos определяется hadoop.security.auth_to_local кластера.

    Сборка и проверка из исходников

    Команды показывают 3.5; замените ветку на 2.7, 2.10, 3.2, 3.3 или 3.4 для нужного адаптера.

    ./mvnw -pl agents/grantforge-agent-hdfs-3.5 -am package
    ./mvnw -pl plugins/grantforge-plugin-hdfs,agents/grantforge-agent-hdfs-3.5,core/grantforge-plugin-host -am test

    Артефакт агента оказывается в agents/grantforge-agent-hdfs-3.5/target/grantforge-agent-hdfs-3.5-<GrantForge-version>.jar. Юнит-тесты покрывают обратные вызовы авторизации NameNode, конфигурацию, метаданные версии и решения по политикам; тесты WebHDFS и Kerberos запускают временные локальные сервисы. Перед выходом в продакшен проверьте на целевом кластере также чтение и запись, создание, переименование, рекурсивное удаление, переключение HA и поведение кэша после сетевого сбоя.

    Интеграционная проверка выполняется фазой verify с использованием Testcontainers (юнит-тесты не запускают кластер; verify требует работающего демона Docker):

    ./mvnw -pl agents/grantforge-agent-hdfs-3.5 -am verify
    # Та же точка входа, что и в nightly
    bash script/ci/hdfs_integration.sh 3.5
    # Одна ветка или полная матрица
    bash script/ci/hdfs_integration.sh all

    Тесты используют контейнерные образы Apache Hadoop с зафиксированными версиями и помещают фактически упакованный jar агента в classpath NameNode. Testcontainers создаёт изолированную сеть и управляет жизненным циклом NameNode и DataNode, проверяя чтение и запись, создание, дозапись, переименование, удаление, рекурсивный запрет и запрет снимков, встроенные права и аудит, обновление политик, перезапуск NameNode с подписанным кэшем после отключения сервера политик, а также строгий режим с откатом на встроенные права при отсутствии снимка.

    Требуется работающий Docker-демон, и должно быть разрешено скачивание тестовых образов. Если Docker недоступен, тесты завершаются ошибкой; они никогда не пропускаются молча. Файловый клиент работает внутри контейнера Hadoop, а HTTP-служба политик использует проброс портов Testcontainers на хост; внешний кластер Hadoop не нужен. Контейнеры и тестовая сеть удаляются после тестов, а логи сохраняются в agents/grantforge-agent-hdfs-3.5/target/hdfs-testcontainers.

    HA-тест запускает два NameNode, один DataNode и один JournalNode и настраивает независимые имена экземпляров и каталоги кэша для обоих агентов. Он использует логический клиент HDFS, чтобы вручную переключить активный узел, и проверяет чтение, запись и запрет политик после переключения. Единственный JournalNode существует только для тестирования: отказоустойчивость кворума не проверяется, автоматическое переключение на основе ZooKeeper не используется.

    Тест автоматического HA (Hadoop с 2.10 по 3.5, Java 17 и 21) запускает ZooKeeper, три JournalNode, два NameNode, каждый со своим ZKFC, и один DataNode. Проверяется, что после аварийной остановки активного NameNode ZooKeeper передаёт роль другому, который продолжает применять политики и записывает отказы под своим экземпляром; что политики, опубликованные во время отсутствия NameNode, применяются, когда он возвращается как standby, и продолжают действовать после возврата роли, без отката к старой версии; что без сервера политик принявший роль NameNode продолжает работать по имеющемуся снимку и отправляет аудит после возвращения сервера; и что при остановке одного из трёх JournalNode запись проходит, а при остановке двух запись завершается ошибкой и активный NameNode останавливается, а не продолжает работу без кворума. Вариант с Kerberos, только на Hadoop 3.5.0, добавляет JournalNode, которые входят по keytab и работают только по HTTPS, ZKFC, которые аутентифицируются в ZooKeeper через SASL, и znode выборов, доступные только principal NameNode (неаутентифицированный клиент ZooKeeper не может их даже прочитать); проверяется, что при остановке активного NameNode роль принимает другой и продолжает применять политики к пользователям Kerberos, что клиент без билета всегда получает отказ и что роль возвращается, когда первый NameNode снова доступен. JournalNode работают под principal с коротким именем NameNode, потому что JournalNode отдаёт edits только полному principal NameNode или запрашивающему с собственным коротким именем, а HTTP-аутентификация передаёт ему только короткие имена. Автоматический HA на Hadoop 2.7 не проверен: его клиент переключается, только пока разрешается имя хоста каждого NameNode, а имя остановленного контейнера перестаёт разрешаться, поэтому клиент завершается с UnknownHostException, не пробуя другой NameNode.

    Тест Kerberos выполняется на всех шести линиях (Java 17 и 21): KDC работает в JVM теста, NameNode и DataNode запускаются в защищённом режиме со своими keytab, DataNode передаёт данные только после SASL и работает только по HTTPS, а WebHDFS использует SPNEGO. Проверяется, что политики GrantForge применяются к чтению и записи после сопоставления principal с короткими именами, что пользователь без политики получает отказ, что отказы записываются в аудит под коротким именем, что клиент без билета получает отказ без отката к простой аутентификации и что перезапущенный NameNode снова входит в систему и продолжает применять политики.

    Общие нативные модульные тесты выполняются в agents/grantforge-agent-hdfs-native/src/test, а не компилируются во все шесть адаптеров. Тесты специфичных для версии callbacks остаются в соответствующих нумерованных модулях. Общие исходники контейнерных тестов в agents/grantforge-agent-hdfs-common/src/test/shared по-прежнему компилируются в нумерованные производственные модули. Отдельный Maven-проект для тестов не создаётся; Testcontainers остаётся test-зависимостью. Nightly проверяет все шесть версий Hadoop на тестовых хостах Java 17/21; JVM внутри контейнеров соответствует таблице выше. Отчёты и логи сохраняются.

    Точки расширения Hadoop и семантику прав см. в API Apache Hadoop 3.5.0 и руководстве по правам HDFS.

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