Перейти к основному содержимому

Модели контроля доступа

· 10 мин. чтения

1. Введение

В этой статье мы рассмотрим различные модели управления доступом, как реализовать их на практике.

2. Что такое модель контроля доступа?

Общим требованием для приложений, особенно веб-приложений, является то, что некоторые действия могут быть выполнены только в том случае, если заданный набор условий, также называемый политикой, удовлетворен . Хорошо, это очень общее требование, поэтому давайте приведем несколько примеров:

  • Интернет-форум: только участники могут публиковать новые сообщения или отвечать на существующие
  • Интернет-магазин: обычный пользователь может видеть только свои заказы
  • Банковский бэк-офис: менеджер по работе с клиентами может управлять портфелем своих клиентов. В дополнение к этим портфелям он/она также может управлять портфелем другого клиента менеджера по работе с клиентами, когда он/она временно недоступен (например, в отпуске), и первый выступает в качестве его коллеги.
  • Цифровой кошелек: платежи ограничены до 500 долларов США с 20:00 до 08:00 часового пояса пользователя.

Модель управления доступом , которую мы примем для данного приложения, будет отвечать за оценку входящего запроса и принятие решения: может ли запрос быть обработан или нет. В последнем случае результатом обычно будет сообщение об ошибке, которое отправляется обратно пользователю.

./4f6b560242a72de2f3d8171ed3221f27.png

Очевидно, что каждый из этих примеров требует различного подхода при авторизации данного запроса.

3. Типы моделей контроля доступа

Из предыдущих примеров видно, что для принятия решения о разрешении/запрете нам необходимо учитывать различные аспекты, связанные с запросом:

  • Идентификатор, связанный с запросом. Обратите внимание, что даже анонимный доступ имеет форму идентификации здесь
  • Объекты/ресурсы, на которые направлен запрос
  • Действие, выполняемое над этими объектами/ресурсами
  • Контекстная информация о запросе. Время суток, часовой пояс и используемый метод аутентификации являются примерами такого рода контекстной информации.

Мы можем разделить модель управления доступом на три типа:

  • Управление доступом на основе ролей (RBAC)
  • Списки контроля доступа (ACL)
  • Контроль доступа на основе атрибутов (ABAC)

Независимо от ее типа, мы обычно можем идентифицировать следующие сущности в модели:

  • PEP или точка применения политики : перехватывает запрос и разрешает его выполнение или нет в зависимости от результата, возвращаемого PDP .
  • PDP или точка принятия решения по политике : оценивает запросы с использованием политики для принятия решения о доступе.
  • PIP или пункт информации о политике : хранит и/или опосредует доступ к информации, используемой PDP для принятия решений о доступе.
  • PAP или точка администрирования политик: управляет политиками и другими операционными аспектами, связанными с принятием решений о доступе.

На следующей диаграмме показано, как эти объекты логически связаны друг с другом:

./04c489544489543eb1e84a3a7168b84b.png

Важно отметить, что, хотя они и изображаются как автономные объекты, на практике мы обнаружим, что некоторые или даже все элементы модели встроены в само приложение .

Кроме того, в этой модели не рассматривается, как установить личность пользователя. Тем не менее, этот аспект можно учитывать при принятии решения о разрешении обработки запроса.

Теперь давайте посмотрим, как мы можем применить эту общую архитектуру к каждой из вышеперечисленных моделей.

4. Управление доступом на основе ролей

В этой модели процесс принятия решения PDP состоит из двух этапов:

  • Во-первых, он восстанавливает роли, связанные с идентификатором входящего запроса.
  • Затем он пытается сопоставить эти роли с политикой запросов.

Конкретная реализация этой модели присутствует в спецификации Java EE в виде аннотации @HttpConstraint и ее XML-эквивалента . Это типичное использование аннотации применительно к сервлету:

@WebServlet(name="rbac", urlPatterns = {"/protected"})
@DeclareRoles("USER")
@ServletSecurity(
@HttpConstraint(rolesAllowed = "USER")
)
public class RBACController extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().println("Hello, USER");
}
}

Для сервера Tomcat мы можем идентифицировать объекты модели управления доступом, описанные ранее, следующим образом:

  • PEP: Клапан безопасности , который проверяет наличие этой аннотации в целевом сервлете и вызывает связанную область , чтобы восстановить личность, связанную с текущим запросом.
  • PDP: Реализация Realm , которая решает, какие ограничения применять для данного запроса.
  • PIP: любой бэкэнд, используемый конкретной реализацией Realm , в котором хранится информация, связанная с безопасностью. Для модели RBAC ключевой информацией является набор ролей пользователя, который обычно извлекается из репозитория LDAP.
  • Хранилище политик: в данном случае аннотация — это само хранилище.
  • PAP: Tomcat не поддерживает динамические изменения политики, так что в этом нет реальной необходимости. Однако, проявив некоторое воображение, мы можем идентифицировать его с любым инструментом, используемым для добавления аннотаций и/или редактирования файла WEB-INF/web.xml приложения.

Другие системы безопасности (например, Spring Security) работают аналогичным образом. Ключевым моментом здесь является то, что даже если конкретный фреймворк не соответствует в точности нашей общей модели, его сущности все еще существуют, даже если они несколько замаскированы.

4.1. Определения ролей

Что именно представляет собой роль? На практике роль — это просто именованный набор связанных действий, которые пользователь может выполнять в конкретном приложении . Они могут быть грубо или точно определены по мере необходимости, в зависимости от требований приложения.

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

Что касается ассоциации между пользователями и ролями, мы можем использовать прямой или косвенный подход. В первом мы назначаем роли непосредственно пользователям. В последнем есть промежуточная сущность, обычно группа пользователей, которой мы назначаем роли:

./587a129c6fa169b529a26a48cfa3b33a.png

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

Точно так же непрямая модель также позволяет нам легко изменять существующие определения ролей, обычно после рефакторинга приложения.

5. Списки контроля доступа

Контроль безопасности на основе ACL позволяет нам определять ограничения доступа к отдельным объектам домена. Это контрастирует с RBAC, где ограничения обычно применяются ко всем категориям объектов. В приведенном выше примере форума мы можем использовать подход, основанный только на RBAC, для определения возможности чтения и создания новых сообщений.

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

Для этого простого примера мы можем просто добавить один столбец автора в базу данных и использовать его, чтобы разрешить или запретить доступ к действию редактирования. Но что, если мы хотим поддерживать совместное редактирование? В этом случае нам нужно сохранить список всех людей, которые могут редактировать пост — ACL.

При работе со списками ACL возникает несколько практических вопросов:

  • Где мы храним ACL?
  • Как эффективно применять ограничения ACL при извлечении больших коллекций объектов?

Библиотека ACL Spring Security — хороший пример библиотеки ACL. Он использует выделенную схему базы данных и кэши для реализации ACL и тесно интегрирован со Spring Security. Это короткий пример, адаптированный из нашей статьи об этой библиотеке , показывающий, как реализовать управление доступом на уровне объекта:

@PreAuthorize("hasPermission(#postMessage, 'WRITE')")
PostMessage save(@Param("noticeMessage")PostMessage postMessage);

Еще одним хорошим примером ACL является система разрешений, используемая Windows для защиты объектов. Каждый защищаемый объект (например, файлы, каталоги, процессы и многие другие) имеет присоединенный к нему дескриптор безопасности , который содержит список отдельных пользователей/групп и связанных с ними разрешений:

./3b846e2852af51f1047aeda7bb0723fc.png

Windows ACL довольно мощны (или сложны, в зависимости от того, кого мы спрашиваем), позволяя администраторам назначать разрешения отдельным пользователям и/или группам. Кроме того, отдельные записи определяют разрешения/запреты для каждого возможного действия.

6. Контроль доступа на основе атрибутов

Модели управления на основе атрибутов позволяют принимать решения о доступе на основе не только идентификатора, действия и целевого объекта, но и контекстуальной информации, связанной с запросом .

Стандарт XACML , пожалуй, самый известный пример этой модели, использующей документы XML для описания политик доступа. Вот как мы можем использовать этот стандарт для описания правила вывода средств из цифрового кошелька:

<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" 
PolicyId="urn:foreach:atm:WithdrawalPolicy"
Version="1.0"
RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:deny-overrides">
<Target/>
<Rule RuleId="urn:oasis:names:tc:foreach:WithDrawalPolicy:Rule1" Effect="Deny">
<Target>
<AnyOf>
<AllOf>
... match rule for the withdrawal action omitted
</AllOf>
</AnyOf>
</Target>
<Condition>
... time-of-day and amount conditions definitions omitted
</Condition>
</Rule>
</Policy>

Полное определение правила доступно в Интернете .

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

Каждое правило содержит цели, которые определяют логическое выражение с использованием атрибутов запроса. Дополнительно правило может также содержать один или несколько элементов Condition , определяющих его применимость.

Во время выполнения PEP управления доступом на основе XACML создает экземпляр RequestContext и отправляет его на PDP для оценки. Затем механизм оценивает все применимые правила и возвращает решение о доступе.

Тип информации, представленной в этом RequestContext , является основным аспектом, который отличает эту модель от предыдущих. Возьмем, к примеру, XML-представление контекста запроса, созданное для авторизации вывода средств в нашем приложении цифрового кошелька:

<Request 
xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
CombinedDecision="true"
ReturnPolicyIdList="false">

<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
... action attributes omitted
</Attributes>
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment">
... environment attributes (e.g., current time) omitted
</Attributes>
<Attributes Category="urn:foreach:atm:withdrawal">
... withdrawal attributes omitted
</Attributes>
</Request>

Когда мы отправим этот запрос в механизм оценки правил XAML в 21:00, ожидаемым результатом будет отказ в этом выводе средств, поскольку он превышает максимально допустимую сумму для ночных транзакций.

Ключевым преимуществом модели ABAC является ее гибкость. Мы можем определить и, что более важно, изменить сложные правила, просто изменив политику. В зависимости от реализации мы можем делать это даже в режиме реального времени.

6.1. XACML4J

XACML4J — это реализация стандарта XACML 3.0 для Java с открытым исходным кодом. Он предоставляет механизм оценки и реализации связанных сущностей, требуемые моделью ABAC. Его основным API является интерфейс PolicyDecisionPoint , который, что неудивительно, реализует логику PDP.

После того, как мы построили PDP, его использование требует двух шагов. Во-первых, мы создаем и заполняем RequestContext информацией о запросе, который мы хотим оценить:

... attribute categories creation omitted
RequestContext request = RequestContext.builder()
.attributes(actionCategory,environmentCategory,atmTxCategory)
.build();

Здесь каждый параметр xxxCategory содержит набор атрибутов для соответствующей категории . Полный код использует доступные сборщики для создания тестового запроса на вывод 1200 долларов США в 21:00. Кроме того, мы также можем создать объект RequestContext непосредственно из любого JAXB -совместимого источника.

Далее мы передаем этот объект методуsolve () сервиса PolicyDecisionPoint для его оценки: ``

ResponseContext response = pdp.decide(request);
assertTrue(response.getDecision() == Decision.DENY);

Возвращенный ResponseContext содержит объект Decision с результатом оценки политики. Кроме того, он также может возвращать диагностическую информацию и дополнительные обязательства и/или рекомендации PEP. Обязательства и советы — отдельная тема, поэтому мы не будем их здесь затрагивать. В этом учебном пособии от Axiomatic показано, как мы можем использовать эту функцию для реализации нормативного контроля в типичном приложении системы записей.

6.2. ABAC без XACML

Сложность XACML обычно делает его излишним для большинства приложений. Однако мы по-прежнему можем использовать базовую модель в наших приложениях. В конце концов, мы всегда можем реализовать более простую версию, адаптированную к конкретному варианту использования, возможно, внедрив всего несколько параметров, верно?

Что ж, любой опытный разработчик знает, чем это заканчивается…

Сложный аспект любой реализации ABAC заключается в том, как извлечь атрибуты из полезной нагрузки запроса . Стандартные методы для вставки пользовательской логики перед обработкой запроса, такие как фильтры сервлетов или перехватчики JAX-RS, имеют доступ только к необработанным данным полезной нагрузки.

Поскольку современные приложения, как правило, используют JSON или аналогичные представления, PEP должен декодировать его, прежде чем он сможет извлечь какой-либо атрибут полезной нагрузки. Это означает потенциальный удар по использованию ЦП и памяти, особенно для больших полезных нагрузок.

В этом случае лучшим подходом является использование АОП для реализации PEP. В этом случае код обработчика аспекта имеет доступ к декодированной версии полезной нагрузки.

7. Заключение

В этой статье мы описали различные модели управления доступом и то, как приложения используют их для обеспечения соблюдения правил доступа.

Как обычно, полный исходный код примеров можно найти на GitHub .