Безопасное проектирование модуля валидатора
Перед внедрением модуля валидатора внимательно прочтите и полностью усвойте этот раздел. Неисправный валидатор потенциально хуже, чем полное отсутствие аутентификации, как из-за ложного чувства безопасности, которое он создает, так и потому, что он может способствовать атакам на другие компоненты экосистемы OAuth.
Обязанности валидатора
Хотя разные модули могут использовать совершенно разные подходы к проверке токенов, реализациям, как правило, необходимо выполнить три отдельных действия:
Проверка токена
В первую очередь валидатор должен убедиться, что представленный токен действительно является действительным токеном Bearer для использования в аутентификации клиента. Правильный способ сделать это зависит от поставщика, но обычно он включает либо криптографические операции для доказательства того, что токен был создан доверенной стороной (автономная проверка), либо представление токена этой доверенной стороне для выполнения проверки (онлайн-проверка).
Онлайн-валидация, обычно реализуемая с помощью интроспекции токенов OAuth, требует меньшего количества шагов от модуля валидатора и позволяет централизованно аннулировать токен в случае его кражи или неправильной выдачи. Однако она требует от модуля выполнения как минимум одного сетевого вызова на каждую попытку аутентификации (все они должны завершиться в течение настроенного времени ожидания аутентификации). Кроме того, провайдер может не предоставлять конечные точки интроспекции для использования внешними серверами ресурсов.
Офлайн-валидация гораздо сложнее и обычно требует от валидатора ведения списка доверенных ключей подписи для провайдера, а затем проверки криптографической подписи токена вместе с его содержимым. Реализации должны в точности следовать инструкциям провайдера, включая любую проверку эмитента («откуда этот токен?»), целевой аудитории («для кого предназначен этот токен?») и срока действия («когда этот токен можно использовать?»). Поскольку между модулем и провайдером нет связи, токены не могут быть централизованно аннулированы с помощью этого метода; Внедрение офлайн-валидаторов может потребовать ограничения максимальной продолжительности срока действия токена.
Если токен не может быть проверен, модуль должен немедленно завершиться с ошибкой. Дальнейшая аутентификация/авторизация бессмысленна, если токен носителя не был выдан доверенной стороной.
Авторизация клиента
Далее валидатор должен убедиться, что конечный пользователь предоставил клиенту разрешение на доступ к серверу от его имени. Обычно это включает проверку областей действия, назначенных токену, чтобы убедиться, что они охватывают доступ к базе данных для текущих параметров HBA.
Цель этого шага — предотвратить получение клиентом OAuth токена обманным путем. Если валидатор требует, чтобы все токены содержали области действия, охватывающие доступ к базе данных, поставщик должен затем громко запросить у пользователя предоставление такого доступа во время процесса. Это дает ему возможность отклонить запрос, если клиент не должен использовать свои учетные данные для подключения к базам данных.
Хотя можно установить авторизацию клиента без явных областей действия, используя внеполосные знания о развернутой архитектуре, это исключает пользователя из процесса, что не позволяет ему выявлять ошибки развертывания и позволяет незаметно использовать любые такие ошибки. Доступ к базе данных должен быть строго ограничен только доверенными клиентами, если пользователям не запрашиваются дополнительные области действия.
Даже если авторизация не удалась, модуль может продолжить извлечение информации об аутентификации из токена для использования в аудите и отладке.
Аутентификация конечного пользователя
Наконец, валидатор должен определить идентификатор пользователя для токена, либо запросив эту информацию у поставщика, либо извлекая ее из самого токена, и вернуть этот идентификатор серверу (который затем примет окончательное решение об авторизации, используя конфигурацию HBA). Этот идентификатор будет доступен в рамках сессии через system_user и записан в журналы сервера, если включена опция log_connections.
Разные поставщики могут записывать различную информацию об аутентификации конечного пользователя, обычно называемую утверждениями (claims). Поставщики обычно документируют, какие из этих утверждений достаточно надежны для использования при принятии решений об авторизации, а какие нет. (Например, вероятно, нецелесообразно использовать полное имя конечного пользователя в качестве идентификатора для аутентификации, поскольку многие поставщики позволяют пользователям произвольно изменять свои отображаемые имена.) В конечном итоге, выбор того, какое утверждение (или комбинацию утверждений) использовать, зависит от реализации поставщика и требований приложения. Обратите внимание, что анонимный/псевдонимный вход также возможен при включении делегирования usermap.
Общие рекомендации по кодированию
При реализации проверки токенов разработчикам следует учитывать следующее:
Конфиденциальность токенов
Модули не должны записывать токены или их части в журнал сервера. Это справедливо даже в том случае, если модуль считает токен недействительным; злоумышленник, который вводит клиента в заблуждение, заставляя его общаться с неправильным поставщиком, не должен иметь возможности получить этот (в остальном действительный) токен с диска.
Реализации, отправляющие токены по сети (например, для онлайн-проверки токенов у поставщика), должны аутентифицировать участника сети и обеспечить использование надежной защиты передачи данных.
Ведение журналов
Модули могут использовать те же средства ведения журналов, что и стандартные расширения; однако правила отправки записей в журнал клиенту несколько отличаются на этапе аутентификации соединения. В целом, модули должны регистрировать проблемы проверки на уровне COMMERROR и возвращать обычный результат, вместо использования ERROR/FATAL для восстановления стека, чтобы избежать утечки информации неаутентифицированным клиентам.
Прерываемость
Модули должны оставаться прерываемыми сигналами, чтобы сервер мог корректно обрабатывать тайм-ауты аутентификации и сигналы завершения работы от pg_ctl. Например, блокирующие вызовы на сокетах, как правило, следует заменять кодом, который обрабатывает как события сокетов, так и прерывания без состояний гонки (смотрите WaitLatchOrSocket(), WaitEventSetWait() и др.), а длительные циклы должны периодически вызывать CHECK_FOR_INTERRUPTS(). Несоблюдение этих рекомендаций может привести к неработоспособности серверных сессий.
Тестирование
Широкий спектр тестирования системы OAuth выходит далеко за рамки данной документации, но, как минимум, негативное тестирование следует считать обязательным. Разработать модуль, который позволяет авторизованным пользователям входить в систему, несложно; вся суть системы заключается в том, чтобы не допускать неавторизованных пользователей.
Документация
Реализации валидаторов должны документировать содержимое и формат аутентифицированного идентификатора, который сообщается серверу для каждого конечного пользователя, поскольку администраторам баз данных может потребоваться использовать эту информацию для построения карт pg_ident. Например, это адрес электронной почты? Идентификационный номер организации? UUID? Также следует указать, безопасно ли использовать модуль в режиме delegate_ident_mapping=1, и какая дополнительная конфигурация необходима для этого.
Авторизация пользователей (делегирование Usermap)
Стандартным результатом работы модуля проверки является идентификатор пользователя, который сервер затем сравнивает с любыми настроенными сопоставлениями в pg_ident.conf и определяет, имеет ли конечный пользователь право на подключение. Однако OAuth сам по себе является фреймворком авторизации, и токены могут содержать информацию о привилегиях пользователя. Например, токен может быть связан с организационными группами, к которым принадлежит пользователь, или содержать список ролей, которые может выполнять пользователь, и дублирование этой информации в локальных usermap для каждого сервера может быть нежелательным.
Чтобы полностью обойти сопоставление имен пользователей и передать дополнительную ответственность за авторизацию подключений пользователей модулю проверки, HBA может быть настроен с параметром delegate_ident_mapping. Затем модуль может использовать области действия токенов или эквивалентный метод для определения того, разрешено ли пользователю подключаться в рамках желаемой роли. Идентификатор пользователя по-прежнему будет записываться сервером, но он не играет никакой роли в определении того, следует ли продолжать подключение.
При использовании этой схемы сама аутентификация является необязательной. Пока модуль сообщает об авторизации соединения, вход в систему будет продолжаться, даже если идентификатор пользователя вообще не зарегистрирован. Это позволяет реализовать анонимный или псевдонимный доступ к базе данных, при котором сторонний поставщик выполняет всю необходимую аутентификацию, но не предоставляет серверу никакой информации, идентифицирующей пользователя. Некоторые поставщики могут создавать анонимизированный идентификационный номер, который можно записать для последующего аудита.
Делегирование Usermap обеспечивает наибольшую архитектурную гибкость, но превращает модуль валидатора в единую точку отказа для авторизации соединения. Используйте с осторожностью.