Перейти к содержанию

Объектные разрешения

InfraVision использует новую структуру разрешений на основе объектов, которая заменяет встроенную модель разрешений Django. Объектные разрешения позволяют администратору предоставлять пользователям или группам возможность выполнять действия над произвольными подмножествами объектов в InfraVision, а не над всеми объектами определённого типа. Например, можно предоставить пользователю разрешение на просмотр только площадок в определённом регионе или на изменение только VLAN с числовым ID в определённом диапазоне.

Разрешение в InfraVision представляет собой связь между несколькими компонентами:

  • Тип(ы) объекта — один или несколько типов объектов в InfraVision
  • Пользователь(и)/Группа(ы) — один или несколько пользователей или групп пользователей
  • Действие(я) — действие(я), которые можно выполнять над объектом
  • Ограничения — произвольный фильтр, используемый для ограничения предоставленных действий определённым подмножеством объектов

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

Действия

Существует четыре основных действия, которые могут быть разрешены для каждого типа объекта в InfraVision, примерно аналогичных соглашению CRUD (создание, чтение, обновление и удаление):

  • View (Просмотр) — получить объект из базы данных
  • Add (Добавление) — создать новый объект
  • Change (Изменение) — изменить существующий объект
  • Delete (Удаление) — удалить существующий объект

В дополнение к ним разрешения также могут предоставлять пользовательские действия, которые могут потребоваться для конкретной модели или плагина. Например, разрешение run для скриптов позволяет пользователю выполнять пользовательские скрипты. Их можно указать при предоставлении разрешения в поле "дополнительные действия".

Примечание

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

Ограничения

Ограничения выражаются в виде JSON-объекта или списка, представляющего фильтр запросов Django. Это тот же синтаксис, который вы бы передали методу filter() QuerySet при выполнении запроса с использованием Django ORM. Как и в фильтрах запросов, двойные подчёркивания могут использоваться для обхода связанных объектов или вызова выражений поиска. Некоторые примеры запросов и соответствующие им определения показаны ниже.

Все атрибуты, определённые в одном JSON-объекте, применяются с логическим И. Например, предположим, что вы назначаете разрешение для модели площадки со следующими ограничениями.

{
  "status": "active",
  "region__name": "Americas"
}

Разрешение предоставит доступ только к площадкам, которые имеют статус "active" И которые назначены региону "Americas".

Для достижения логического ИЛИ с другим набором ограничений определите несколько объектов в списке. Например, если вы хотите ограничить разрешение VLAN с ID от 100 до 199 или со статусом "reserved", сделайте следующее:

[
  {
    "vid__gte": 100,
    "vid__lt": 200
  },
  {
    "status": "reserved"
  }
]

Кроме того, если для типа объекта назначено несколько разрешений, их совокупные ограничения будут объединены с использованием логической операции "ИЛИ".

Токен пользователя

При определении ограничения разрешения администраторы могут использовать специальный токен $user для ссылки на текущего пользователя в момент оценки. Это может быть полезно, например, для ограничения пользователей редактированием только собственных записей журнала. Такое ограничение может быть определено как:

{
  "created_by": "$user"
}

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

Разрешения по умолчанию

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

Примеры определений ограничений

Ограничения Описание
{"status": "active"} Статус — active
{"status__in": ["planned", "reserved"]} Статус — active ИЛИ reserved
{"status": "active", "role": "testing"} Статус — active И роль — testing
{"name__startswith": "Foo"} Имя начинается с "Foo" (с учётом регистра)
{"name__iendswith": "bar"} Имя заканчивается на "bar" (без учёта регистра)
{"vid__gte": 100, "vid__lt": 200} VLAN ID больше или равен 100 И меньше 200
[{"vid__lt": 200}, {"status": "reserved"}] VLAN ID меньше 200 ИЛИ статус — reserved

Применение разрешений

Просмотр объектов

Объектные разрешения работают путём фильтрации запроса к базе данных, сгенерированного по запросу пользователя, для ограничения набора возвращаемых объектов. При получении запроса InfraVision сначала определяет, аутентифицирован ли пользователь и предоставлено ли ему разрешение на выполнение запрошенного действия. Например, если запрошенный URL — /dcim/devices/, InfraVision проверит наличие разрешения dcim.view_device. Если пользователю не назначено это разрешение (напрямую или через назначение группы), InfraVision вернёт HTTP-ответ 403 (запрещено).

Если разрешение предоставлено, InfraVision скомпилирует все указанные ограничения для модели и действия. Например, предположим, что пользователю назначены два разрешения, предоставляющих доступ на просмотр модели устройства, со следующими ограничениями:

[
    {"site__name__in":  ["NYC1", "NYC2"]},
    {"status":  "offline", "tenant__isnull":  true}
]

Это предоставляет пользователю доступ к просмотру любого устройства, назначенного площадке с именем NYC1 или NYC2, ИЛИ имеющего статус "offline" и без назначенного арендатора. Эти ограничения эквивалентны следующему ORM-запросу:

Site.objects.filter(
    Q(site__name__in=['NYC1', 'NYC2']),
    Q(status='active', tenant__isnull=True)
)

Создание и изменение объектов

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