Единый сервис аутентификации

Введение

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

Если компания успешна и объемы работы растут, то наступает момент, когда один человек перестает справляться. И тогда в компанию нанимаются новые сотрудники. Но, когда число сотрудников в компании увеличивается, появляются проблемы, например:

  • каждый сотрудник должен выполнять только свои бизнес-задачи и не иметь доступа к чужим;

  • каждый сотрудник должен видеть только связанную со своими бизнес-задачами информацию;

  • у каждой задачи должен быть ответственный за ее выполнение сотрудник.

Чтобы решить эти проблемы и правильно разграничить доступ, нужно понимать, кто из сотрудников хочет выполнить действие (аутентификация) и может ли он это сделать (авторизация - разрешение).

Подходы управления доступом

Впервые контроль доступа включал модели дискреционного (англ. Discretionary Access Control, DAC) и мандатного доступов (англ. Mandatory Access Control, MAC).

DAC - Дискретная модель, доступ к объектам, данным или функциям, предоставляется явно указанным субъектам, пользователям или группам пользователей.

MAC - Мандатное управление доступом, заключается в разделении информации по степени секретности, а пользователей по уровням допуска к этой информации.

Самой сложной проблемой является авторизация. Существует несколько подходов к ее решению, широкое распространение получил контроль на основе ролей (role-based access control, RBAC). На основе этих ролей проверяется возможность выполнения пользователем того или иного действия.

RBAC - Управление доступом на основе ролей, где доступ к объектам системы формируется с учётом специфики их применения на основе роли субъектов в каждый момент времени.

Для определения модели RBAC используются следующие соглашения:

  • S = Субъект (англ. Subject) = Человек или автоматизированный агент (множество пользователей);

  • R = Роль (англ. Role) = Рабочая функция или название, которое определяется на уровне авторизации (множество ролей);

  • P = Разрешения (англ. Permissions) = Утверждения режима доступа к ресурсу (множество прав доступа на объекты системы);

  • SE = Сессия (англ. Session) = Соответствие между S, R и/или P

  • SA = Назначение субъекта (англ. Subject Assignment)

  • PA: R → 2p — функция, определяющая для каждой роли множество прав доступа; при этом для каждого p из P существует r из R такая, что p принадлежит PA(r); (англ. Permission Assignment)

  • RH = Частично упорядоченная иерархия ролей (англ. Role Hierarchy).

    Один субъект может иметь несколько ролей.
    Одну роль могут иметь несколько субъектов.
    Одна роль может иметь несколько разрешений.
    Одно разрешение может принадлежать нескольким ролям.

Роли назначаются субъектам, вследствие чего субъекты получают те или иные разрешения через роли. RBAC требует именно такого назначения, а не прямого - назначение разрешений субъектам, иначе это приводит к сложно контролируемым отношениям между субъектами и разрешениями.

Если бизнес-правила одномерны и все действия можно разбить по ролям (бухгалтер, менеджер, администратор и т. п.), такого подхода будет достаточно. Тогда одному бизнес-правилу будет соответствовать одна роль.

Но бизнес-правила неизбежно усложняются и становятся многомерными. Это приводит к тому, что одного атрибута (роли) для выражения бизнес-правил становится недостаточно и начинают добавляться другие атрибуты (город, страна, филиал, день недели, владелец, лимит и т.п.).

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

  • одно бизнес-правило «размазывается» среди множества ролей и становится неочевидным, что усложняет понимание такого правила и его поддержку;

  • начинается взрывной рост числа ролей, что значительно усложняет управление ими.

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

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

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

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

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

Можно явно выделить несколько категорий атрибутов:

../_images/security_abac_attributes.png

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

Простые правила описываются простыми условиями:

../_images/security_simple_rule.png

Многомерные правила в этой модели не становятся более сложными:

../_images/security_complex_rules.png

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

../_images/security_busines_rules.png

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

../_images/security_busines_rules_filter.png

Определение правил

Бизнес правила ABAC в PromUC определяются при помощи шаблонов политики в виде файлов формата YAML.

Политика состоит из следующих полей:

Поля политики

Поле

Тип

Значения

Описание

uid

<string>

строковое значение, которое однозначно идентифицирует политику

description

<string>

здесь хранится описание политики

rules

<rules_block>

«Блок правил»

targets

<targets_block>

«Блок целей»

effect

<string>

allow, deny

может быть либо «разрешить», либо «запретить»

priority

<number>

0

предоставляет числовое значение, указывающее вес политики, когда ее решение конфликтует с другой политикой в соответствии с алгоритмом оценки HighestPriority. По умолчанию в этом поле установлено значение 0 для всех политик

«Цели» указывают, к каким экземплярам элементов управления доступом применяется политика. Так называемые цели политики. «Правила» определяют условия для атрибутов целей.

subject_id:
- "<id_string>"
- "<id_string>"
resource_id:
- "<id_string>"
- "<id_string>"
action_id:
- "<id_string>"
- "<id_string>"

Пример:

subject_id:
- a
- b
resource_id:
- ab*
action_id:
- "*"

В этом примере определено, что политика применима только когда идентификатор субъекта установлен на «a» или «b», и когда идентификатор ресурса начинается с «ab». Действие может иметь любое значение идентификатора.

По умолчанию:

subject_id: "*"
resource_id: "*"
action_id: "*"

Правила - логические выражения, определенные в атрибутах целевых экземпляров элементов управления доступом:

subject: "<boolean_expression>"
resource: "<boolean_expression>"
action: "<boolean_expression>"
context: "<boolean_expression>"

где <boolean_expression> является блоком для логического выражения.

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

Простое логическое выражение состоит из пары ключ-значение, как показано ниже:

Пример:

subject:
  "$.name.firstName":
    condition: Eq
    value: Carl
  "$.name.lastName":
    condition: Eq
    value: Rubin
resource:
- "$.name":
    condition: Eq
    value: Default
- "$.type":
    condition: Eq
    value: Book

В целом правило гласит, что субъект должен иметь значение "имя" равное "Карл", а "фамилия" - "Рубин". Аналогичным образом, ресурс должен иметь атрибут "имя" с значением "По-умолчанию" ИЛИ "тип" с значением "Книга".

Блоки состояния

В ABAC поддерживается следующие типы блоков <condition_expression>:

Числовое условие:

condition: <string>

Eq: значение атрибута равно тому, что в "value"
Neq: значение атрибута не равно тому, что в "value"
Gt: значение атрибута больше, чем в "value"
Gte: значение атрибута больше или равно, тому, что в "value"
Lt: значение атрибута меньше, чем в "value"
Lte: значение атрибута меньше или равно, тому, что в "value"

values: <number>

Пример:

condition: Lte
value: 1.5

Возможные значения для строки:

condition: <string>

Equals: строка значения атрибута равна тому, что в "value"
NotEquals: строка значения атрибута не равна тому, что в "value"
Contains: значение атрибута содержит строку в "value"
NotContains: значение атрибута не содержит строку в "value"
StartsWith: значение атрибута начинается со строки в "value"
EndsWith: значение атрибута заканчивается строкой в "value"
RegexMatch: строка значения атрибута соответствует шаблону регулярных выражений в "value"
case_insensitive: <bool>: флаг условия без учета регистра строки. Это необязательное поле и по умолчанию установлено значение False.

values: <string>

Пример:

condition: StartsWith
value: Cal
case_insensitive: true

Возможные значения для массивов:

condition: <string>

AllIn: все элементы массива атрибутов являются элементом "values"
AllNotIn: ни один из элементов массива атрибутов не является элементом "values"
AnyIn: один или несколько элементов массива атрибутов являются элементом "values"
AnyNotIn: один или несколько элементов массива атрибутов не являются элементом "values"
IsIn: значение атрибута (обработано как одно значение) является элементом "values"
IsNotIn: значение атрибута (обработано как одно значение) не является элементом "values"

values: <list>

Пример:

condition: AnyIn
values:
- Example1
- Example2

Возможные значения для условия массива

condition: <string>

IsEmpty: коллекция значений атрибутов пуста
IsNotEmpty: коллекция значений атрибутов не пуста

condition: IsEmpty

Возможные значения для типа JSON

condition: <string>

EqualsObject: значение атрибута объекта JSON равно тому, что в "value"
values: Содержит объект JSON
condition: EqualsObject
value:
name: Sam

Возможные значения для типа логического условия.

condition: <string>

AnyOf: значение атрибута удовлетворяет любому из условий в "values"
AllOf: значение атрибута удовлетворяет всем условиям в "values"
values": <list<condition_expression>>

Содержит список блоков <condition_expression>

Пример:

condition: AllOf
values:
- condition: Lt
  value: 1.5
- condition: Gt
  value: 0.5

Возможные значения для типа логического условия.

condition: <string>

Not: значение атрибута не удовлетворяет условию в "value"

"values": Содержит блок <condition_expression>.

Пример:

condition: Not
value:
  condition: Eq
  value: 1.5

Тип условия свойства атрибутов

condition: <string>

EqualsAttribute: значение атрибута равно значению атрибута в расположении «path» элемента управления доступом «ace».
NotEqualsAttribute: значение атрибута не равно значению атрибута в расположении «path» элемента управления доступом ace».
IsInAttribute: значение атрибута входит в значении списка атрибута в расположении «path» элемента управления доступом «ace».
IsNotInAttribute: значение атрибута не входит в значение списка атрибута в расположении «path» элемента управления доступом «ace».
AllInAttribute: все значения списка атрибутов соответствуют значениям списка, в расположении «path» элемента управления доступом «ace».
AllNotInAttribute: все значения списка атрибутов не соответствуют значениям списка, в расположении «path» элемента управления доступом «ace».
AnyInAttribute: любые значения списка атрибутов соответствуют, значениям списка в расположении «path» элемента управления доступом «ace».
AnyNotInAttribute: любые значения списка атрибутов не соответствуют значениям списка в расположении «path» элемента управления доступом «ace».

ace: <string>

Определяет элемент управления доступом. Значение этого поля должно быть "subject", "resource", "action", или "context"

path: <string>

Указан путь атрибута в нотации ObjectPath элемента управления доступом в "ace"

Пример:

condition: EqualsAttribute
ace: context
path: "$.network.name"

Прочее условие определяет состояние сети "CIDR"

condition: CIDR

CIDR: IP-адрес в значении атрибута находится в блоке CIDR в "value"

value: <string>

Содержит блок CIDR в виде строки.

Пример:

..code-block:

condition: CIDR
value: 10.0.0.0/16

Прочее условие определяет тип условия

condition: CIDR

Any: атрибут содержит любое значение, включая нулевое значение
Exists: атрибут существует, проверяя, не является ли он нулевым
NotExists: атрибут не завершается, проверяя, что он пуст

Пример:

condition: Any

Пример шаблона политики:

attributes:
    visa:
        class: PhpAbac\Example\Visa
        type: resource
        fields:
            country.code:
                name: Code Pays
            lastRenewal:
                name: Dernier renouvellement

    country:
        class: PhpAbac\Example\Country
        type: resource
        fields:
            code:
                name: Code

rules:
    travel-to-germany:
        attributes:
            main_user.visas:
                comparison_type: array
                comparison: contains
                with:
                    visa.country.code:
                        comparison_type: string
                        comparison: isEqual
                        value: DE
                    visa.lastRenewal:
                        comparison_type: datetime
                        comparison: isMoreRecentThan
                        value: -1Y

Запрос на доступ

Запрос на доступ - это объект данных, содержащий всю информацию, необходимую для оценки политик и принятия решения о предоставлении доступа.

{
  "subject": {
      "id": <string>,
      "attributes": <attribute_block>
  },
  "resource": {
      "id": <string>,
      "attributes": <attribute_block>
  },
  "action": {
      "id": <string>,
      "attributes": <attribute_block>
  },
  "context": <attribute_block>
}

Пример:

{
  "subject": {
    "id": "a",
    "attributes": {
      "firstName": "Иван",
      "lastName": "Иванов"
    }
  },
  "resource": {
    "id": "a",
    "attributes": {
      "name": "Calendar"
    }
  },
  "action": {
    "id": "",
    "attributes": {}
  },
  "context": {}
}

Журнал событий безопасности

Система ведёт журнал событий безопасности, в который попадают следующие события:

  • неуспешная попытка входа пользователя (с меткой времени в UTC формате, объект доступа)

  • успешный вход пользователя (с меткой времени в UTC формате и идентифитором пользователя, объект доступа)

  • выход пользователя (с меткой времени в UTC формате и идентифитором пользователя)

  • автоматический выход из сессии пользователя (с меткой времени в UTC формате и идентифитором пользователя, причина выхода)

  • изменение профиля пользователя (с меткой времени в UTC формате и указанием изменений и их инициатора)

  • смена пароля пользователем (с меткой времени в UTC формате)

  • навигация по разделам системы

  • отправка команд (с меткой времени в UTC формате, объект управления, результат выполнения)

  • запуск и остановка сервисов системы (с меткой времени в UTC формате и причиной)

Примеры журнала:

../_images/user_activity.jpg ../_images/user_activity_2.jpg